Angular2 local components / pattern reuse

I am writing several Angular2 templates that have duplicate parts with different containers. In this case, the presentation may change if everything is grouped, and if the multi-section mode is enabled. Sorry for 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 would really like to reuse parts of this without creating a completely separate component and putting it all together, which would require a TypeScript file and template. One method will 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 understand that the above is a rough sketch and probably won't work as it is, but the apparent inability to reuse parts of the kind like this is unsuccessful. This question is pretty simple in React, if I understand correctly.

I’m curious how other people decided to reuse parts without thinking about writing a new component (which our designers then need to know and style, etc.).). Thanks.

+5
source share
4 answers

If your sections are identical in structure, just different in data, you can come up with a more general model. Instead of directly referring to category and thing , map them to a common object that you populate in the service before moving on to the view.

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

Here the items will either be filled out of things or categories.

Then you can call it like this

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

Basically, you normalize the view, regardless of the actual objects.

+4
source

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

+3
source

Compute the component in the template recursively.

isList control the part to be used, false by default.

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 } 
0
source

Now you can use <ng-template>

 <ng-template #headerPanel> <header> This is my reusable header. </header> </ng-template> 

Then use like this:

  <ng-container *ngTemplateOutlet="headerPanel"></ng-container> 

Official documents

Note. I'm not knowledgeable enough to explain the difference between [ngTemplateOutlet] and *ngTemplateOutlet , but if someone wants to edit this answer or add another, feel free to.

0
source

Source: https://habr.com/ru/post/1247088/


All Articles