Angular2 ngFor, <template> 的用法
https://toddmotto.com/angular-ngfor-template-element#lttemplategt-element
Angular ngFor,<template> and the compiler
90% Unlimited Downloads Choose from Over 300,000 Vectors,Graphics & Photos.ads viaCarbon
Angular We’ll also be exploring some other under-the-hood properties of Table of contents
Using the ngFor directiveIn this section,we’ll be taking a look at the featureset NgModule importFirst of all,to use Our import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
bootstrap: [AppComponent]
})
export class AppModule {}
For this article,we’ll be including a further // ...
import { ContactCardComponent } from './contact-card.component';
@NgModule({
declarations: [
AppComponent,
ContactCardComponent
],
// ...
})
export class AppModule {}
Our import { Component, Input } from '@angular/core';
import { Contact } from './models/contact.interface';
@Component({
selector: 'contact-card',
template: `
<div class="contact-card">
<p>{{ contact.name }} ( {{ contact.age }} )</p> <p>{{ contact.email }}</p> </div> `
})
export class ContactCardComponent {
@Input()
contact: Contact;
}
So now we’re all setup,what’s next? Iterating collectionsNow that our @Component({...})
export class AppComponent implements OnInit {
contacts: Observable<Contact[]>;
ngOnInit() {
this.contacts = Observable.of([
{
"id": 1,
"name": "Laura",
"email": "lbutler0@latimes.com",
"age": 47
},
{
"id": 2,
"name": "Walter",
"email": "wkelley1@goodreads.com",
"age": 37
},
{
"id": 3,
"email": "wgutierrez2@smugmug.com",
"age": 49
},
{
"id": 4,
"name": "Jesse",
"email": "jarnold3@com.com",
{
"id": 5,
"name": "Irene",
"email": "iduncan4@oakley.com",
"age": 33
}
]);
}
}
As mentioned in the introduction,I’m using Using ngForNow we’re setup,we can look into our @Component({
selector: 'app-root',
template: `
<div class="app">
<ul>
<li>
<contact-card></contact-card> </li> </ul> </div> `
})
You can see I’m declaring One way we could do this is using <ul>
<li *ngFor="let contact of contacts">
<contact-card></contact-card>
</li>
</ul>
There are a few things happening here,the first you’ll notice a The So,now we have <ul>
<li *ngFor="let contact of contacts">
<contact-card [contact]="contact"></contact-card>
</li>
</ul>
If you’re using a static array,or binding the result of an Observable to the template,you can leave the template as it currently is. However,we can optionally bind the Observable directly to the template,which means we’ll need the <ul>
<li *ngFor="let contact of contacts | async">
<contact-card [contact]="contact"></contact-card>
</li>
</ul>
You can check a live output of what we’ve covered so far here: Using trackBy for keysIf you’re coming from an Angular 1.x background,you’ll have likely seen “track by” when using an So what do these do? They associate the objects,or keys,with the particular DOM nodes,so should anything change or need to be re-rendered,the framework can do this much more efficiently. Angular’s This is where <ul>
<li *ngFor="let contact of contacts | async; trackBy: trackById;">
<contact-card [contact]="contact"></contact-card>
</li>
</ul>
Here we’ve added trackById(index, contact) {
return contact.id;
}
All this function does is use a custom tracking solution for our collection. Instead of using object identity,we’re telling Angular here to use the unique If your API returns unique data,then using that would be a preferable solution over You can check a live output of what we’ve covered here: Capturing “index” and “count”The Let’s create another variable called To log out the index,we can simply interpolate <ul>
<li *ngFor="let contact of contacts | async; let i = index;">
Index: {{ i }}
<contact-card [contact]="contact"></contact-card>
</li>
</ul>
This will give us every index,starting from <ul>
<li *ngFor="let contact of contacts | async; let i = index; let c = count;">
Index: {{ i }}
Count: {{ c }}
<contact-card [contact]="contact"></contact-card>
</li>
</ul>
The <ul>
<li *ngFor="let contact of contacts | async; let i = index; let c = count;">
<contact-card
[contact]="contact"
[collectionLength]="c"
(update)="onUpdate($event, i)">
</contact-card>
</li>
</ul>
You can check a live output of what we’ve covered here: Accessing first,evenFour more properties exposed by export class NgForRow {
constructor(public $implicit: any, public index: number, public count: number) {}
get first(): boolean { return this.index === 0; }
get last(): boolean { return this.index === this.count - 1; }
get even(): boolean { return this.index % 2 === 0; }
get odd(): boolean { return !this.even; }
}
As I mentioned above,the
Using this,we can add conditionally apply things such as styling,or hook into the For this quick demo,we’ll use <ul>
<li
*ngFor="let contact of contacts | async; let o = odd; let e = even;"
[ngClass]="{
'odd-active': o,
'even-active': e
}">
<contact-card
[contact]="contact"
(update)="onUpdate($event, index)">
</contact-card>
</li>
</ul>
And some styles: @Component({
selector: 'app-root',
styles: [`
.odd-active { background: purple; color: #fff; }
.even-active { background: red; color: #fff; }
`],
template: `
<div class="app">
<ul>
<li
*ngFor="let contact of contacts | async; let o = odd; let e = even;"
[ngClass]="{ 'odd-active': o,'even-active': e }">
<contact-card
[contact]="contact"
(update)="onUpdate($event,index)">
</contact-card> </li> </ul> </div> `
})
We won’t demonstrate You can check a live output of what we’ve covered here: <template> elementWe mentioned earlier in this article that we’d look at understanding what the So in this next section,we’ll take a deeper dive on When using an asterisk ( <template> and Web ComponentsSo,what is the <script id="myTemplate" type="text/ng-template">
<div>
My awesome template!
</div> </script>
This overrides the Web Components introduced something similar to this idea,called the <template id="myTemplate">
<div>
My awesome template!
</div>
</template>
To grab our above template and instantiate it,we’d do this in plain JavaScript: <div id="host"></div> <script>
let template = document.querySelector('#myTemplate');
let clone = document.importNode(template.content, true);
let host = document.querySelector('#host');
host.appendChild(clone);
</script>
Note how we have You may have seen this term floating around Angular in a few ways,such as ngFor and <template>So how does the above Let’s start from the basic <ul>
<li *ngFor="let contact of contacts | async">
<contact-card [contact]="contact"></contact-card>
</li>
</ul>
And demonstrate the <template ngFor let-contact [ngForOf]="contacts | async">
<li>
<contact-card [contact]="contact"></contact-card>
</li>
</template>
That’s a lot different! What’s happening here? When we use
Let’s continue,and understand what ngFor and embedded view templatesFirst thing’s first, @Directive({selector: '[ngFor][ngForOf]'})
export class NgFor implements DoCheck, OnChanges {...}
Here,Angular is using attribute selectors as the value of The directive uses Angular’s compiler transforms any
In our case,Angular will construct a view that creates everything from the <!-- view -->
<li>
<contact-card [contact]="contact"></contact-card>
</li>
<!-- /view -->
It also creates an invisible view container to contain all instances of the template,acting as a placeholder for content. The view container Angular has created essentially wraps the “views”,in our case this is just inside the A pseudo-output might look like this: <ul>
<!-- view container -->
<!-- view -->
<li>
<contact-card [contact]="contact"></contact-card>
</li>
<!-- /view -->
<!-- view -->
<li>
<contact-card [contact]="contact"></contact-card>
</li>
<!-- /view -->
<!-- view -->
<li>
<contact-card [contact]="contact"></contact-card>
</li>
<!-- /view -->
<!-- /view container -->
</ul>
Context and passing variablesThe next step is understanding how Angular passes the context to each <template ngFor let-contact [ngForOf]="contacts | async">
<li>
<contact-card [contact]="contact"></contact-card>
</li>
</template>
So now we’ve understood Because Whilst Angular is creating each changes.forEachIdentityChange((record: any) => {
const viewRef = <EmbeddedViewRef<NgForRow>>this._viewContainer.get(record.currentIndex);
viewRef.context.$implicit = record.item;
});
Alongside this section of code,we can also see how our aforementioned for (let i = 0, ilen = this._viewContainer.length; i < ilen; i++) {
const viewRef = <EmbeddedViewRef<NgForRow>>this._viewContainer.get(i);
viewRef.context.index = i;
viewRef.context.count = ilen;
}
This is how we can then access the <ul>
<template ngFor let-i="index" let-c="count" let-contact [ngForOf]="contacts | async">
<li>
<contact-card [contact]="contact"></contact-card>
</li>
</template>
</ul>
Note how we’re supplying You can check out the Award-winning Angular 1.x and Angular 2 coursesBecome an expert with my comprehensive Angular 1.5+ and Angular 2 courses (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |