Angular 2:ngFor 完成时的回调

IT技术 javascript angularjs angular ngfor
2021-02-08 01:47:19

在 Angular 1 中,我编写了一个自定义指令(“repeater-ready”),用于ng-repeat在迭代完成时调用回调方法:

if ($scope.$last === true)
{
    $timeout(() =>
    {
        $scope.$parent.$parent.$eval(someCallbackMethod);
    });
}

标记中的用法:

<li ng-repeat="item in vm.Items track by item.Identifier"
    repeater-ready="vm.CallThisWhenNgRepeatHasFinished()">

如何ngFor在 Angular 2 中实现类似的功能

6个回答

您可以为此使用@ViewChildren

@Component({
  selector: 'my-app',
  template: `
    <ul *ngIf="!isHidden">
      <li #allTheseThings *ngFor="let i of items; let last = last">{{i}}</li>
    </ul>

    <br>

    <button (click)="items.push('another')">Add Another</button>

    <button (click)="isHidden = !isHidden">{{isHidden ? 'Show' :  'Hide'}}</button>
  `,
})
export class App {
  items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];

  @ViewChildren('allTheseThings') things: QueryList<any>;

  ngAfterViewInit() {
    this.things.changes.subscribe(t => {
      this.ngForRendred();
    })
  }

  ngForRendred() {
    console.log('NgFor is Rendered');
  }
}

原始答案在这里 https://stackoverflow.com/a/37088348/5700401

效果很好。谢谢!
2021-03-24 01:47:19
惊人的解决方案!
2021-03-26 01:47:19
这个问题的最佳解决方案。
2021-03-30 01:47:19
这应该是公认的答案,因为它使用 Angular 提供的内容正确处理了视图状态的问题。其他一切都只是一个黑客。
2021-04-02 01:47:19

你可以使用这样的东西(ngFor 局部变量):

<li *ngFor="#item in Items; #last = last" [ready]="last ? false : true">

然后您可以使用 setter 拦截输入属性更改

  @Input()
  set ready(isReady: boolean) {
    if (isReady) someCallbackMethod();
  }
至少,这不适用于li元素,但适用于嵌套在其中的自定义组件。
2021-03-15 01:47:19
需要添加一个新组件来完成这项工作。看这个演示:github.com/xmeng1/ngfor-finish-callback
2021-03-15 01:47:19
与此一起使用: <li *ngFor="item in Items; last = last" [attr.ready]="last ? false : true">
2021-03-17 01:47:19
我认为代码应该是这样的` *ngFor="#item of Items;`不是吗?顺便说一句代码抛出错误 ready is not know native property blabla...
2021-04-02 01:47:19
这不像所有其他人所说的那样工作,模板解析错误以在 <li> 中使用
2021-04-06 01:47:19

对我来说,使用 Typescript 在 Angular2 中工作。

<li *ngFor="let item in Items; let last = last">
  ...
  <span *ngIf="last">{{ngForCallback()}}</span>
</li>

然后你可以处理使用这个功能

public ngForCallback() {
  ...
}
不,它不会被执行 items.length 次。它会永远持续下去,哈哈
2021-03-26 01:47:19
请不要使用此解决方案,除非您的 ChangeDetectionStrategy 设置为 OnPush。
2021-03-28 01:47:19
嘿亚历克斯,你是对的,这个函数会被 Items.lenght 次执行。这不是一个很好的方法,适用于小而快的事情。
2021-04-04 01:47:19
对我来说,这会被执行一百万次
2021-04-05 01:47:19
@MarcoNoronha 我测试了它,它不会永远持续下去
2021-04-14 01:47:19

解决方案非常简单。如果您需要知道何时ngFor完成将所有 DOM 元素打印到浏览器窗口,请执行以下操作:

1. 添加占位符

为正在打印的内容添加占位符:

<div *ngIf="!contentPrinted">Rendering content...</div>

2. 添加容器

display: none为内容创建一个容器打印完所有项目后,请执行display: blockcontentPrinted是一个组件标志属性,默认为false

<ul [class.visible]="contentPrinted"> ...items </ul>

3.创建回调方法

添加onContentPrinted()到组件中,ngFor完成后自动禁用

onContentPrinted() { this.contentPrinted = true; this.changeDetector.detectChanges(); }

并且不要忘记使用ChangeDetectorRef来避免ExpressionChangedAfterItHasBeenCheckedError

4. 使用 ngForlast

last在 上声明变量ngForli当此项是最后一项,在内部使用它来运行一个方法

<li *ngFor="let item of items; let last = last"> ... <ng-container *ngIf="last && !contentPrinted"> {{ onContentPrinted() }} </ng-container> <li>

  • 使用contentPrinted组件标志属性onContentPrinted() 运行一次
  • 用于ng-container不影响布局。
“微不足道”,但需要解释 4 个步骤
2021-03-31 01:47:19

使用 [attr.ready] 代替 [ready],如下所示

 <li *ngFor="#item in Items; #last = last" [attr.ready]="last ? false : true">