3

I am pretty new in Angular 2 and I am not so into JavaScript\TypeScript (I came from Java) and I have some doubt about an example that I am studying related how to a component can use a property defined in another component (property\event binding). The example show how an array of element declared in a child component can be used and shown in the parent component.

So I have the app-component that is the parent component.

This is the app-component "view" named app-component.html:

<div class="container">
  <app-cockpit></app-cockpit>
  <hr>
  <div class="row">
    <div class="col-xs-12">
      <app-server-element
        *ngFor="let serverElement of serverElements"
        [element]="serverElement"></app-server-element>
    </div>
  </div>
</div>

From what I can undestand this code generate app-server-element (another component of my application with its layout) starting from the serverElements array that is defined into the app.component.ts class, this one:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  serverElements = [{type: 'server', name: 'TestServer', content: 'Just a Test'}];
}

So here I have a this first doubt: doing:

<app-server-element
    *ngFor="let serverElement of serverElements"
    [element]="serverElement">
</app-server-element>

The *ngFor directive is iterating on the serverElements array that is defined into the app.component.ts class (related to the main app-component component) and not on the server-element.component.ts class (related to the component).

It works fine but it seems to me a little strange. Why? My idea is that this *ngFor directive is declared into the HTML code of the app-component.html related to the , so the iteration is on an array that is defined in the related class.

Is it or am I missing something?

AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
  • 1
    The loop belongs to parent component (app-conmponent), and it renders N number of child components (server-whatever), passing a prop `element` === each element of the array from parent component. The view belongs to parent component, so it can use data only from parent script. – Egor Stambakio Jun 13 '17 at 12:44

1 Answers1

6

In angular, when you write a directive preceded by an aserisk that is actually syntactic sugar for a more complex structure. For *ngFor, the documentation gives this example:

<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
  ({{i}}) {{hero.name}}
</div>

The *ngFor is first rewritten to a template attribute:

<div template="ngFor let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
  ({{i}}) {{hero.name}}
</div>

Then the template attribute is extracted out to an ng-template directive wrapping the element that contained the original *ngFor.

<ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
  <div [class.odd]="odd">({{i}}) {{hero.name}}</div>
</ng-template>

The same rewriting happens with your code:

<app-server-element
    *ngFor="let serverElement of serverElements"
    [element]="serverElement">
</app-server-element>

is actually just a shorthand for:

<ng-template ngFor let-serverElement [ngForOf]="serverElements">
    <app-server-element [element]="serverElement"></app-server-element>
</ng-template>

From the expanded form of the ngFor it should now be obvious that serverElements is referenced entirely outside the app-server-element component.

Duncan
  • 92,073
  • 11
  • 122
  • 156