programing

각도 2: ngFor가 완료되면 콜백

telecom 2023. 3. 26. 09:38
반응형

각도 2: ngFor가 완료되면 콜백

Angular 1에 사용할 커스텀 지시문("반복 가능")을 작성했습니다.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앵귤러 2에?

이 목적으로 @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

다음과 같은 것을 사용할 수 있습니다(ng로컬 변수의 경우).

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

그런 다음 설정기를 사용하여 입력 속성 변경을 가로챌 수 있습니다.

  @Input()
  set ready(isReady: boolean) {
    if (isReady) someCallbackMethod();
  }

저는 Typescript를 사용하여 Angular2에서 작업합니다.

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

그러면 이 기능을 사용하여 처리할 수 있습니다.

public ngForCallback() {
  ...
}

해결책은 아주 사소한 것이다.언제인지 알고 싶다면ngFor는 브라우저 창에 모든 DOM 요소 인쇄를 완료하고 다음 절차를 수행합니다.

1. 플레이스 홀더 추가

인쇄할 컨텐츠의 자리 표시자를 추가합니다.

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

2. 용기 추가

컨테이너를 만듭니다.display: none내용을 확인합니다.모든 아이템이 인쇄되면display: block.contentPrinted컴포넌트 플래그 속성입니다.기본값은 입니다.false:

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

3. 콜백 메서드를 작성하다

더하다onContentPrinted()컴포넌트에 접속할 수 있습니다.이 컴포넌트는 다음 시간 후에 자동으로ngFor완료:

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

그리고 잊지 말고ChangeDetectorRef피하다ExpressionChangedAfterItHasBeenCheckedError.

4. ngFor 사용last가치

선언하다last에 따라 변동하다.ngFor실내에서 사용하다li이 항목이 마지막 항목일 때 메서드를 실행하려면:

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

  • 사용하다contentPrinted실행할 구성 요소 플래그 속성onContentPrinted() 한 번만.
  • 사용하다ng-container레이아웃에 영향을 주지 않도록 합니다.

[ready] 대신 다음과 같이 [attr.ready]를 사용합니다.

<li *ngFor="#항목, #last = last" [attr.ready]="last ? false : true">

RC3에서 인정된 답변이 작동하지 않는 것을 발견했습니다.하지만, 저는 이 문제를 해결할 방법을 찾았습니다.MDL componentHandler를 실행하여 컴포넌트를 업그레이드하려면 ngFor가 언제 완료되었는지 알아야 합니다.

우선 지시가 필요합니다.

업그레이드 컴포넌트.directive.ts

import { Directive, ElementRef, Input } from '@angular/core';

declare var componentHandler : any;

@Directive({ selector: '[upgrade-components]' })
export class UpgradeComponentsDirective{

    @Input('upgrade-components')
    set upgradeComponents(upgrade : boolean){
        if(upgrade) componentHandler.upgradeAllRegistered();
    }
}

다음으로 컴포넌트로 Import하여 디렉티브에 추가합니다.

import {UpgradeComponentsDirective} from './upgradeComponents.directive';

@Component({
    templateUrl: 'templates/mytemplate.html',
    directives: [UpgradeComponentsDirective]
})

이제 HTML에서 "upgrade-components" 속성을 true로 설정합니다.

 <div *ngFor='let item of items;let last=last' [upgrade-components]="last ? true : false">

이 Atribut이 true로 설정되면 @Input() 선언으로 메서드가 실행됩니다.이 경우 componentHandler.upgradeAllRegistered()가 실행됩니다.단, 원하는 대로 사용할 수 있습니다.ngFor 문의 '마지막' 속성에 바인딩함으로써 종료 시 실행됩니다.

[ attr . upgrade - components ]는 현재 bonafide 디렉티브이기 때문에 네이티브아트리뷰트가 아닌 경우에도 사용할 필요가 없습니다.

저는 이 문제에 대해 데모를 쓰고 있습니다.이 이론은 받아들여진 대답에 기초하고 있지만, 이 대답은 완전하지 않다.li를 받아들일 수 있는 커스텀 컴포넌트여야 합니다.readydiscloss.discloss.

저는 이 문제에 대해 완전한 데모를 쓰고 있습니다.

새로운 컴포넌트를 정의합니다.

'@angular/core'에서 {Component, Input, OnInit} 가져오기;

@Component({
  selector: 'app-li-ready',
  templateUrl: './li-ready.component.html',
  styleUrls: ['./li-ready.component.css']
})
export class LiReadyComponent implements OnInit {

  items: string[] = [];

  @Input() item;
  constructor() { }

  ngOnInit(): void {
    console.log('LiReadyComponent');
  }

  @Input()
  set ready(isReady: boolean) {
    if (isReady) {
      console.log('===isReady!');
    }
  }
}

템플릿

{{item}}

앱 구성 요소에서의 사용

<app-li-ready *ngFor="let item of items;  let last1 = last;" [ready]="last1" [item]="item"></app-li-ready>

콘솔에 로그가 표시되고 모든 항목 문자열이 인쇄된 후 isReady가 인쇄됩니다.

ngFor가 어떻게 후드 아래에서 요소를 렌더링하는지 자세히 알아보지 못했습니다.그러나 관찰 결과, 반복되는 각 항목마다 두 번 이상 식을 평가하는 경향이 있는 것으로 나타났습니다.

이로 인해 ngFor 'last' 변수를 체크할 때 이루어지는 모든 타입스크립트 메서드 호출이 여러 번 트리거될 수 있습니다.

ng에 의해 타이프스크립트 메서드에 대한1개의 콜을 보증하려면 ngFor가 후드 아래에서 수행하는 여러 표현 재평가로부터 작은 보호를 추가해야 합니다.

(지시를 통해) 이를 수행하는 한 가지 방법은 다음과 같습니다.

지시 코드

import { Directive, OnDestroy, Input, AfterViewInit } from '@angular/core';

@Directive({
  selector: '[callback]'
})
export class CallbackDirective implements AfterViewInit, OnDestroy {
  is_init:boolean = false;
  called:boolean = false;
  @Input('callback') callback:()=>any;

  constructor() { }

  ngAfterViewInit():void{
    this.is_init = true;
  }

  ngOnDestroy():void {
    this.is_init = false;
    this.called = false;
  }

  @Input('callback-condition') 
  set condition(value: any) {
      if (value==false || this.called) return;

      // in case callback-condition is set prior ngAfterViewInit is called
      if (!this.is_init) {
        setTimeout(()=>this.condition = value, 50);
        return;
      }

      if (this.callback) {
        this.callback();
        this.called = true;
      }
      else console.error("callback is null");

  }

}

모듈에서 위의 디렉티브를 선언한 후(그 방법을 알고 있지 않은 경우 물어보고 코드 스니펫으로 업데이트하기를 희망합니다), ngFor에서 디렉티브를 사용하는 방법은 다음과 같습니다.

<li *ngFor="let item of some_list;let last = last;" [callback]="doSomething" [callback-condition]="last">{{item}}</li>

'doSomething'은 typeScript 파일의 메서드 이름입니다.ngFor가 항목을 통해 반복 작업을 마쳤을 때 호출합니다.

주의: 'doSomething'에는 괄호 '(')가 없습니다.이것은 타이프스크립트 메서드에 대한 참조를 전달했을 뿐 실제로는 여기서 호출하지 않기 때문입니다.

마지막으로 'doSomething' 메서드는 다음과 같습니다.

public doSomething=()=> {
    console.log("triggered from the directive's parent component when ngFor finishes iterating");
}

언급URL : https://stackoverflow.com/questions/35819264/angular-2-callback-when-ngfor-has-finished

반응형