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
}
Другие вопросы по тегам