Angular2 локальные компоненты / повторное использование шаблона
Я пишу несколько шаблонов Angular2, которые содержат повторяющиеся части в разных контейнерах. В этом случае представление может измениться, если вещи сгруппированы и если включен многосекционный режим. Пожалуйста, извините за длинный пример, но что-то вроде этого:
<template [ngIf]="isCategoryGrouped">
<div *ngFor="#categories of categories">
<div>{{ categories.category.name }}</div>
<div *ngFor="#thing of categories.things">
<label *ngIf="isMultiSelectMode">
<input type="checkbox" (change)="updateThingSelection(thing, $event)" />
<img [src]="thing.image" /> {{ thing.name }}
</label>
<a href="javascript: void(0)" (click)="selectThing(thing)" *ngIf="! isMultiSelectMode">
<img [src]="thing.image" /> {{ thing.name }}
</a>
</div>
</div>
</template>
<template [ngIf]="! isCategoryGrouped">
<div *ngFor="#thing of things">
<label *ngIf="isMultiSelectMode">
<input type="checkbox" (change)="updateThingSelection(thing, $event)" />
<img [src]="thing.image" /> {{ thing.name }}
</label>
<a href="javascript: void(0)" (click)="selectThing(thing)" *ngIf="! isMultiSelectMode">
<img [src]="thing.image" /> {{ thing.name }}
</a>
</div>
</template>
Я действительно хотел бы повторно использовать части этого без необходимости писать полностью отдельный компонент и соединять все это вместе, что потребовало бы файла TypeScript и шаблона. Один метод будет с локальными компонентами, что-то вроде этого:
<sub-component selector="thing-list" things="input">
<div *ngFor="#thing of things">
<label *ngIf="isMultiSelectMode">
<input type="checkbox" (change)="updateThingSelection(thing, $event)"/>
<img [src]="thing.image" /> {{ thing.name }}
</label>
<a href="javascript: void(0)" (click)="selectThing(thing)" *ngIf="! isMultiSelectMode">
<img [src]="thing.image" /> {{ thing.name }}
</a>
</div>
</sub-component>
<template [ngIf]="isCategoryGrouped">
<div *ngFor="#categories of categories">
<div>{{ categories.category.name }}</div>
<thing-list things="categories.things" />
</div>
</template>
<thing-list [ngIf]="! isCategoryGrouped" things="things" />
Я понимаю, что вышеизложенное является грубым наброском и, вероятно, не сработает как есть, но очевидная неспособность повторно использовать части вида, как это, вызывает сожаление. Подобные вещи довольно просты в React, если я правильно понимаю.
Мне любопытны элегантные способы, которыми другие решали повторное использование частей обзора, не вдаваясь в детали написания нового компонента (о котором наши дизайнеры должны были бы знать, стиль и т. Д.). Благодарю.
4 ответа
Если ваши разделы идентичны по структуре, просто различаются по данным, вы можете придумать более общую модель. Вместо того, чтобы ссылаться на category
а также thing
непосредственно сопоставьте их в общий объект, который вы заполняете в сервисе, прежде чем он попадет в представление.
<div *ngFor="#item of items">
---
</div>
Здесь предметы будут либо заполнены вещами, либо категориями.
Затем вы можете назвать это так
<component [items]="fromThings"></component>
<component [items]="fromCategories"></component>
Вы в основном нормализуете представление, не завися непосредственно от реальных объектов.
Вы также можете использовать *ngFor
с [ngForTemplate]
или предстоящий NgInsert (имя будет изменено), чтобы сделать части вашего шаблона многократно используемыми.
Теперь вы можете использовать <ng-template>
<ng-template #headerPanel>
<header>
This is my reusable header.
</header>
</ng-template>
Тогда используйте как это:
<ng-container *ngTemplateOutlet="headerPanel"></ng-container>
Примечание: я недостаточно осведомлен, чтобы объяснить разницу между [ngTemplateOutlet]
а также *ngTemplateOutlet
но если кто-то хочет отредактировать этот ответ или добавить другой, не стесняйтесь.
Вызовите компонент рекурсивно в шаблоне.
isList
контролировать, какая часть будет использоваться, по умолчанию false
,
thing.html
<template [ngIf]="isLlist">
<div *ngFor="#thing of things">
<label *ngIf="isMultiSelectMode">
<input type="checkbox" (change)="updateThingSelection(thing, $event)"/>
<img [src]="thing.image" /> {{ thing.name }}
</label>
<a href="javascript: void(0)" (click)="selectThing(thing)" *ngIf="! isMultiSelectMode">
<img [src]="thing.image" /> {{ thing.name }}
</a>
</div>
</template>
<template [ngIf]="!isList">
<template [ngIf]="isCategoryGrouped">
<div *ngFor="#categories of categories">
<div>{{ categories.category.name }}</div>
<my-thing-component [isList]="true" [things]="categories.things"></my-thing-component>
</div>
</template>
<templete [ngIf]="! isCategoryGrouped">
<my-thing-component [isList]="true" [things]="things"></my-thing-component>
</templete>
</template>
thing.component.ts
import {Component,Input} from '@angular/core';
@Component({
selector: 'my-thing-component',
templateUrl: 'thing.html'
})
export class ThingComponent {
@Input() isList = false;
@Input() things;
//Fill in the rest
}