Reputation: 189
Let's say I have a list of items, LI style, like a contact list or to-do things like this:
<li data-letter="J">James Taylor</li>
<li data-letter="J">John Connor</li>
<li data-letter="K">Kyle Connor</li>
<li data-letter="P">Peter Parker</li>
And I need to dynamically add a letter separator between some of those elements, where the result should be something like this:
<separator-component>- J -</separator-component>
<li data-letter="J">James Taylor</li>
<li data-letter="J">John Connor</li>
<separator-component>- K </separator-component>
<li data-letter="K">Kyle Connor</li>
<separator-component>- P -</separator-component>
<li data-letter="P">Peter Parker</li>
Using ViewChildren
I have managed to get the list of QueryList<ViewContainerRef>
for those LI items, and could add the separator components to them, but only after the item I want to insert BEFORE.
This is my component template:
<li #listItems *ngFor="let element of elements" [attr.data-letter]="element.letter">{{ element.name }}</li>
And this is the code (the relevant part of it):
@ViewChildren('listItems', {read: ViewContainerRef}) listItems: QueryList<ViewContainerRef>;
addItem(index: number) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(SeparatorComponent);
const componentRef = this.listItems.toArray()[index].createComponent(componentFactory, 0);
componentRef.changeDetectorRef.detectChanges();
this.letterRefs.push(componentRef);
}
And this is the result I'm getting so far...
<li data-letter="J">James Taylor</li>
<separator-component>- J -</separator-component>
<li data-letter="J">John Connor</li>
<li data-letter="K">Kyle Connor</li>
<separator-component>- K </separator-component>
<li data-letter="P">Peter Parker</li>
<separator-component>- P -</separator-component>
Any suggestions?
Upvotes: 0
Views: 1503
Reputation: 10516
This seems to work:
<ng-container *ngFor="let element of elements" #listItems>
<li [attr.data-letter]="element.letter">{{ element.name }}</li>
</ng-container>
Edit: After closer inspection this works because ng-container
becomes a comment in the DOM before the li
:
<!---->
<li></li>
And createComponent
always renders the new component after (not inside) the ViewContainerRef
, which is the comment in this case.
So it's kind of like doing the following:
<ng-container *ngFor="let element of elements">
<ng-container #listItems></ng-container>
<li [attr.data-letter]="element.letter">{{ element.name }}</li>
</ng-container>
Also, the 0
in this line can be removed because we don't care about an index anymore:
this.listItems.toArray()[index].createComponent(componentFactory, 0);
I actually hope someone has a better answer to this question because it feels like a hack!
Upvotes: 1