Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 local components / template reuse

I'm writing some Angular2 templates that have repetitive portions with different containers. In this case, the view can change if things are grouped and if multi section mode is enabled. Please excuse the long example, but something like this:

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

I'd really like to reuse portions of this without having to write a completely separate component and wire it all together, which would require a TypeScript file and a template. One method would be with local components, something like this:

<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" />

I realize the above is a rough sketch and probably wouldn't work as is, but the apparent inability to reuse portions of the view like this is unfortunate. This sort of thing is quite simple in React, if I understand correctly.

I'm curious about elegant ways others have solved the reuse-of-portions-of-view without going so far as to write a new component (which our designers would then need to know about and style, etc...). Thanks.

like image 933
Yona Appletree Avatar asked Apr 14 '16 01:04

Yona Appletree


People also ask

Can we reuse components in angular?

When having multiple teams working together it makes sense to reuse components between projects. There are two main ways to create reusable components in Angular: Pass inputs to the component, passing the necessary data to the component used for rendering and configuring the component.

Can a component have multiple templates?

Note Although it's possible for a component to render multiple templates, we recommend using an if:true|false directive to render nested templates conditionally instead. Create multiple HTML files in the component bundle.

Can angular component have multiple templates?

You can simply extend your base component and overwrite the template. This allows you to have different components with the exact same functionality, but different templates. Save this answer.

How do you create reusable components in angular 8?

Here, we simply require to use a template. import { Input } from '@angular/core'; import { Component, TemplateRef } from '@angular/core'; @Component({ selector: 'app-page-list', templateUrl: ' ', }) class PageList{ @Input() temRef:TemplateRef; } Parent component hey!


2 Answers

If your sections are identical in structure, just different in data, you could come up with a more generic model. Instead of referring to category and thing directly, map them into a generic object that you populate in a service before it gets to the view.

<div *ngFor="#item of items">
        ---
</div>

Here items would either be populated from things or categories.

You can then call it like so

<component [items]="fromThings"></component>
<component [items]="fromCategories"></component>

You are basically normalizing the view by not depending on the actual objects directly.

like image 154
TGH Avatar answered Sep 22 '22 19:09

TGH


You can also use *ngFor with [ngForTemplate] or the upcoming NgInsert (name will be changed) to make parts of your template reusable.

like image 45
Günter Zöchbauer Avatar answered Sep 22 '22 19:09

Günter Zöchbauer