[Angular 2] More on *ngFor, @ContentChildren & QueryList<>
2016-09-14 23:13
579 查看
In previous artical, we introduce the how to use *ngFor. The limitation for previous solution to display all the heros is we hard cord all heros in our heroes component. First, in real world app, we cannot hard cord; Seond, even we don't hard code, do http instead, it is still not good enough. We should leave Heroes component as dump component, just rendering the ui, no logic should be involved.
So instead of doing this in app.ts:
We try another way like this:
Well, I know, still hard code, but just show how ngFor can be used.
Now, inside 'heroes' tag, we add now 'hero' tag. And we want to display those inside 'heroes' component:
You can see, we have commented out the hard code array. Instead, we use:
'Hero' here, is a element directive:
@ContentChildren will check the Children in HTML DOM tree, which will get:
QueryList<Hero>: Only get 'Hero' directive.
QueryList is a class provided by Angular and when we use QueryList with a ContentChildren Angular populate this with the components that match the query and then keeps the items up to date if the state of the application changes .
However, QueryList requires a ContentChildren to populate it, so let’s take a look at that now.
What's cool about *ngFor, it not only accpets Array, but also any iterable type, we have list of DOM element 'hero', which are iterable, so ngFor will able to display those also.
So instead of doing this in app.ts:
@Component({ selector: 'app', template: ` <heroes> </heroes> ` })
We try another way like this:
@Component({ selector: 'app', template: ` <heroes> <hero name="Superman" id="1"></hero> <hero name="Batman" id="2"></hero> <hero name="BatGirl" id="3"></hero> <hero name="Robin" id="4"></hero> <hero name="Flash" id="5"></hero> <hero name="Zhentian" id="6"></hero> </heroes> ` })
Well, I know, still hard code, but just show how ngFor can be used.
Now, inside 'heroes' tag, we add now 'hero' tag. And we want to display those inside 'heroes' component:
import {Component, ContentChildren, QueryList} from "@angular/core"; import {Hero} from './hero'; /* const HEROES = [ {id: 1, name:'Superman'}, {id: 2, name:'Batman'}, {id: 5, name:'BatGirl'}, {id: 3, name:'Robin'}, {id: 4, name:'Flash'} ];*/ @Component({ selector:'heroes', styleUrls: [ 'heroes.component.css' ], template: ` <table> <thead> <th>Name</th> <th>Index</th> </thead> <tbody> <tr *ngFor="let hero of heroes; let i = index; trackBy: trackBy(hero); let isEven=even; let isFirst=first; let isLast=last;" [ngClass]="{'even': isEven, 'first': isFirst, 'last': isLast}"> <td>{{hero.name}}</td> <td>{{i}}</td> </tr> </tbody> </table> ` }) export class Heroes { //heroes = HEROES; @ContentChildren(Hero) heroes: QueryList<Hero> trackBy(hero){ return hero ? hero.id: undefined; } }
You can see, we have commented out the hard code array. Instead, we use:
@ContentChildren(Hero) heroes: QueryList<Hero>
'Hero' here, is a element directive:
import {Directive, Input} from "@angular/core"; @Directive({ selector: 'hero', }) export class Hero { @Input() id: number; @Input() name:string; }
@ContentChildren will check the Children in HTML DOM tree, which will get:
<hero name="Superman" id="1"></hero> <hero name="Batman" id="2"></hero> <hero name="BatGirl" id="3"></hero> <hero name="Robin" id="4"></hero> <hero name="Flash" id="5"></hero> <hero name="Zhentian" id="6"></hero>
QueryList<Hero>: Only get 'Hero' directive.
QueryList is a class provided by Angular and when we use QueryList with a ContentChildren Angular populate this with the components that match the query and then keeps the items up to date if the state of the application changes .
However, QueryList requires a ContentChildren to populate it, so let’s take a look at that now.
What's cool about *ngFor, it not only accpets Array, but also any iterable type, we have list of DOM element 'hero', which are iterable, so ngFor will able to display those also.
相关文章推荐
- [Angular 2] Share Template Content In Another Template With Content Projection <ng-content>
- Notes On <Professional.Javascript.For.Web.Developer> - 1
- 编译错:The method createSqlQuery(String, List<Object>) is ambiguous for the type
- Notes On <Enterprise AJAX – Strategies for Building High Performance Web Applications> - 1
- [Angular] @ViewChildren and QueryLists (ngAfterViewInit)
- ng1.3+表单验证<AngularJs>
- Notes On <Professional.Javascript.For.Web.Developer> - 2
- Packet for query is too large (1986748 > 1048576). You can change this value on the server by
- CommonJS——<JavaScript:not just for browsers any more!>
- Debug on <python for android> or <kivy>
- Spring JdbcTemplate的queryForList(String sql , Class<T> elementType)易错使用--转载
- startActivityforResult传递List<Object>参数错误问题
- Note On <Pro AngularJS> - 01
- Note on <AngularJS> - Aborted Because Of Too Many Errors In This Book
- Android错误:方法setListAdapter(ArrayAdapter<String>) is undefined for the type String
- Spring JdbcTemplate # queryForList(String sql , Class<T> elementType)
- <Error> <Server> <BEA-002606> <Unable to create a server socket for listening on channel "Default[2
- [Angular] @ContentChildren and QueryList
- Notes On <Codeigniter for Rapid PHP Application Development> - 01
- packet for query is too large <1781> 1024 >. you can change this value on the server by setting the