[Angular 2] More on *ngFor, @ContentChildren & QueryList<>

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:

@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.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值