简体   繁体   中英

How to access variable defined in *ngFor?

In my first Angular 4 application, I defined a list component :

<edm-document *ngFor="let document of documents" class="column is-one-quarter"></edm-document>

Document is an interface :

export interface Document {
    id?: Number,
    name: string,
    filePath: string
}

All is working as expected, ie I get my documents list. But now I would like to access to document variable inside my DocumentComponent (the edm-document tag component)

Inside my DocumentComponent template, if I try this it's not working :

<p>{{ document.name }}</p>

I get this error : DocumentComponent.html:1 ERROR TypeError: Cannot read property 'name' of undefined.

I need to enforce document definition like this, and specify document as an input :

<edm-document *ngFor="let document of documents" [document]="document" class="column is-one-quarter"></edm-document>

Now it works but seems a bit redundant to me as I defined a let in loop. Does that mean the variable defined with let is only available in tag where ngFor directive is set ?

Am I missing something?

Thanks,

Nicolas

it works but seems a bit redundant to me as I defined a let in loop

It is not as redundant as it might seem, which becomes obvious when rewriting things a bit:

  • When not explicitly defining what the component should use (with [document]="document" in your example) then how would your component know that the parent variable is named document ? Consider:

     <edm-document *ngFor="let d of documents" [document]="d"></edm-document>

    One could argue that Angular could introduce some parent variable to access the outer loop variable, but then the component would know how it's going to be used, and could only be used in a loop. Reusable components should not be aware of that.

  • How would it know that it can use that loop variable directly, and does not need some child property instead? Like:

     <edm-document *ngFor="let d of documents" [document]="d.text"></edm-document>

So: your code is just fine.

Initially during DOM rendering the documents object will undefined

  • Use a typesafe ? operator

    <p>{{ document?.name }}</p>
  • Use a *ngIf with a array length condition as below,

     <span *ngIf="documents.length > 0"> <edm-document *ngFor="let document of documents" [document]="document" class="column is-one-quarter"></edm-document> </span>

well you can also do something like this

<edm-document *ngFor="let document of documents" class="column is-one-quarter">
 <span class="something">{{document.name}}</span>
</edm-document>

and in the edm-document.component.html do something like

<ng-content select=".something"></ng-content>

The value (document) of the loop is valid inside of that block where the *ngFor placed. In your case between: <edm-document>..</edm-document>

In your example:

<edm-document *ngFor="let document of documents"class="column is-one-quarter">
<p>{{ document.name }}</p> <!-- document.name is valid -->
</edm-document>
<p>{{ document.name }}</p> <!-- document.name is invalid -->

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM