Multiple switching using ngFor in Angular2

I'm new to angular2, and I'm trying to create a small angular component called a grid , which simply rearranges its contents using a transition.

His pattern

grid component template (grid.component.ts)

<div class="grid"> <div class="row"> <div class="col-xs-4"> <ng-content select="[grid-item-index=0]"></ng-content> </div> <div class="col-xs-4"> <ng-content select="[grid-item-index=1]"></ng-content> </div> <div class="col-xs-4"> <ng-content select="[grid-item-index=2]"></ng-content> </div> </div> <div class="row"> <div class="col-xs-4"> <ng-content select="[grid-item-index=3]"></ng-content> </div> <div class="col-xs-4"> <ng-content select="[grid-item-index=4]"></ng-content> </div> <div class="col-xs-4"> <ng-content select="[grid-item-index=5]"></ng-content> </div> </div> </div> 

And this is part of the parent component that uses it.

parent template

 <grid> <div *ngFor="let item of items; index as i" [attr.grid-item-index]="i"> <span>{{item}}</span> </div> </grid> 

Here is Plunker .

But the result does not display the content. But using ...

 <grid> <div grid-item-index="0">item 0</div> <div grid-item-index="1">item 1</div> <div grid-item-index="2">item 2</div> <div grid-item-index="3">item 3</div> <div grid-item-index="4">item 4</div> <div grid-item-index="5">item 5</div> </grid> 

It works great, and the result was what I expected.

A plunker of this last working case.

You can achieve this result with ngfor or similar.

I tried using the nth-child css pseudo-class to avoid using an index, but it doesn't work either.

UPDATE

I made some progress based on @yurzui's answer (Thanks !!). It allows you to map the contents to the index of the grid table in the view container with the same index value of the table element.

parent.component.html

 <grid> <ng-template *ngFor="let item of items; let i=index" [grid-item-index]="(items.length-1)-i"> <span >{{item}}</span> </ng-template> </grid> 

index-item-index directive

 @Directive({ selector: '[grid-item-index]' }) export class GridItemIndexDirective { @Input('grid-item-index') index: any; constructor(public vcRef: ViewContainerRef, public tRef: TemplateRef) {} } 

grid.component.ts

 @ContentChildren(GridItemIndexDirective) sources: QueryList<GridItemIndexDirective>; @ViewChildren(GridItemIndexDirective) containers: QueryList<GridItemIndexDirective>; constructor( private cdRef:ChangeDetectorRef ) {} ngAfterViewInit() { const len = this.sources.length; for (var i = 0; i < len; i++) { const destinationContainer = this.containers.find(x => x.index == i); const source = this.sources.find(x => x.index == i); if (destinationContainer) { destinationContainer.vcRef.createEmbeddedView(source.tRef); this.cdRef.detectChanges(); // this solves ExpressionChangedAfterItHasBeenCheckedError } } } 

Mark Plunker

+5
source share
1 answer

You can use ngTemplateOutlet to achieve this, but there is another approach that uses a low level API:

parent.component.html

 <grid> <div *ngFor="let item of items"> <span>{{item}}</span> </div> </grid> 

An additional directive that will help us recognize the target index.

 @Directive({ selector: '[grid-item-index]' }) export class GridItemIndexDirective { @Input('grid-item-index') index: any; constructor(public vcRef: ViewContainerRef) {} } 

grid.component.html

 <div class="grid"> <div class="row"> <div class="col-xs-4"> <ng-template grid-item-index="1"></ng-template> </div> <div class="col-xs-4"> <ng-template grid-item-index="2"></ng-template> </div> <div class="col-xs-4"> <ng-template grid-item-index="3"></ng-template> </div> </div> <div class="row"> <div class="col-xs-4"> <ng-template grid-item-index="4"></ng-template> </div> <div class="col-xs-4"> <ng-template grid-item-index="5"></ng-template> </div> <div class="col-xs-4"> <ng-template grid-item-index="6"></ng-template> </div> </div> </div> 

grid.component.ts

 @ContentChild(TemplateRef, { read: ViewContainerRef }) vcRef: ViewContainerRef; @ViewChildren(GridItemIndexDirective) containers: QueryList<GridItemIndexDirective>; ngAfterViewInit() { const len = this.vcRef.length; for( var i = 1; i <= len; i++) { const destinationContainer = this.containers.find(x => x.index == i); if(destinationContainer) { const view = this.vcRef.detach(0); destinationContainer.vcRef.insert(view); } } } 

Plunger example

+2
source

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


All Articles