How is Angular * ngFor loop implemented?

Wondering how the Angular directive *ngFor

actually works under the hood? I would like to know the whole process that occurs when I use a directive.

For downvoters : I've seen the ng-for-of file , although there is none using the passed array *ngFor

, such as the join()

method I know is called. Thanks for the support :) Here is a plunker that shows the behavior: https://plnkr.co/edit/IXVxWrSOhLBgvSal6PWL?p=preview

-five


source to share


1 answer


Here's a high-level overview. Let's say you have defined your template like this:

<span *ngFor="let item of items">{{item}}</span>

      

Then it gets converted to the compiler like this:

<ng-template let-item [ngForOf]="items">
    <span>{{item}}</span>
</ng-template>

      

Angular then applies the directive ngForOf

to the template element. Since this main control is a template, it enters templateRef

. It also introduces viewContainerRef

which acts like an anchor element and will be used to add DOM elements side by side:

  constructor(
       private _viewContainer: ViewContainerRef, 
       private _template: TemplateRef<NgForOfContext<T>>,

      

The directive defines ngForOf

as an input and then waits until it is initialized and makes a difference:

  ngOnChanges(changes: SimpleChanges): void {
      const value = changes['ngForOf'].currentValue;
          this._differ = this._differs.find(value).create(this.ngForTrackBy);

      

Then, in each test run, it compares the values โ€‹โ€‹with the previous values โ€‹โ€‹using this:

  ngDoCheck(): void {
    if (this._differ) {
      const changes = this._differ.diff(this.ngForOf);
      if (changes) this._applyChanges(changes);
    }
  }

      

If the values โ€‹โ€‹are changed, changes are applied that do the following:



1) generates an inline view context for each item in items

context = new NgForOfContext<T>(null !, this.ngForOf, -1, -1)

      

2) creates an inline view in this context with templateRef

that effectively renders the new value to the DOM

this._viewContainer.createEmbeddedView(
                this._template, context , currentIndex);

      

3) adds appropriate values โ€‹โ€‹to the context

  viewRef.context.index = i;
  viewRef.context.count = ilen;
  viewRef.context.$implicit = record.item;`

      

Now, your question is:

although it doesn't explain why the e..g join () method is called on the array passed

It calls the function normalizeDebugBindingValue

here because your application is in development mode:

function normalizeDebugBindingValue(value: any): string {
  try {
    // Limit the size of the value as otherwise the DOM just gets polluted.
    return value != null ? value.toString().slice(0, 30) : value;
                           ^^^^^^^^^^^^^^^
  } catch (e) {
    return '[ERROR] Exception while trying to serialize the value';
  }
}

      

If you turn on production mode, this function will no longer be called, check the plunker .

+6


source







All Articles