web-dev-qa-db-ja.com

Angular複数のテンプレートをコンポーネントに渡す

複数のテンプレートを入力として受け入れるコンポーネントを作成しようとしています。これは私が持っている例です:

_@Component({
    selector: 'data-list',
    styles: [
        require('./data-list.component.scss')
    ],
    template: `
        <ng-template
            *ngFor="let item of itemsData"
            ngFor let-item [ngForOf]="[item]" [ngForTemplate]="itemTemplate"
        ></ng-template>
    `
})

export class DataListComponent {
    @Input() itemsData: any[];
    @ContentChild(TemplateRef) itemTemplate: TemplateRef<ElementRef>;
}
_

ご覧のとおり、これは私が試しているかなり単純なコンポーネントです。このコンポーネントは、表示されるアイテムのデータとアイテムのテンプレートを受け入れるだけです。このコンポーネントは次のように使用できます。

_<data-list [itemsData]="data">
    <ng-template let-item>
        <h1>{{ item.header }}</h1>
        <div>{{ item.content }}</div>
    </ng-template>
</data-list>
_

上記のように、_ng-content_を使用してテンプレートを渡し、DataListComponent@ContentChild(TemplateRef) itemTemplate: TemplateRef<ElementRef>;で読み取ります。

私の質問は、コンポーネントに複数のテンプレートを渡すことができるかどうかです。

例として、アイテムのテンプレートを渡しますが、最初のアイテムの場合は別のテンプレートが必要です。つまり、最初の項目のチェックはDataListComponentで行われますが、それを使用するコンポーネントによって指定されたテンプレートを使用します。

簡単な例:

enter image description here

私はこれに応えるためにそのようなことをすることができます:

_@Component({
    selector: 'data-list',
    styles: [
        require('./data-list.component.scss')
    ],
    template: `
        <span *ngFor="let item of itemsData; let i = index" >
            <ng-template *ngIf="i > 0; else nextTmpl"
                ngFor let-item [ngForOf]="[item]" [ngForTemplate]="itemTemplate"
            ></ng-template>
        </span>
        <ng-template #nextTmpl>
            Next
        </ng-template>
    `
})
_

ただし、「次のテンプレート」は、DataListComponentを使用するコンポーネントによって指定されないため、常に同じテンプレートになります。

11
Daniel Grima

ContentChildデコレーターで使用できる文字列セレクターを使用して、この同じ問題を解決しました。

データリストコンポーネントを使用する場合は、テンプレート変数を指定する必要があります。

<data-list [itemsData]="data">
    <ng-template #firstItemTemplate let-item>
        <h1 style="color:red;">{{ item.header }}</h1>
        <div>{{ item.content }}</div>
    </ng-template>
    <ng-template #standardTemplate let-item>
        <h1>{{ item.header }}</h1>
        <div>{{ item.content }}</div>
    </ng-template>
</data-list>

次に、データリストコンポーネントクラス内で、テンプレート変数をコンポーネントのローカル変数に割り当てます。

@Input() itemsData: any[];
@ContentChild('firstItemTemplate') firstItemTemplate: TemplateRef<ElementRef>;
@ContentChild('standardTemplate') standardTemplate: TemplateRef<ElementRef>;

この後、渡されたテンプレートをデータリストコンポーネントからレンダリングできるようになります。

@Component({
    selector: 'data-list',
    styles: [
        require('./data-list.component.scss')
    ],
    template: `
        <span *ngFor="let item of itemsData; let i = index" >
            <ng-template *ngIf="i == 0; else nextTmpl"
                ngFor let-item [ngForOf]="[item]" [ngForTemplate]="firstItemTemplate"
            ></ng-template>
            <ng-template #nextTmpl 
                ngFor let-item [ngForOf]="[item]" [ngForTemplate]="standardTemplate"
            ></ng-template>
        </span>
    `
})
27
aleroy

代わりにこれを試してください。

@Component({
    selector: 'data-list',
    styles: [
        require('./data-list.component.scss')
    ],
    template: `
        <ng-template ngFor [ngForOf]="itemsData" [ngForTemplate]="itemTemplate"></ng-template>
    `
})

export class DataListComponent {
    @Input() itemsData: any[];
    @ContentChild(TemplateRef) itemTemplate: TemplateRef<ElementRef>;
}
2
Dmitrij Kuba