I have the following component for render a list of options. optionsList
input gets a list that needs to be rendered with a custom format provided from the item
input.
list-box.component.html
<div *ngFor="let option of optionsList; index as it">
<ng-container [ngTemplateOutlet]="item"></ng-container>
</div>
list-box.component.ts
@Component({
selector: 'app-list-box',
templateUrl: './list-box.component.html'
})
export class ListBoxComponent implements OnInit {
@Input('item') public item!:TemplateRef<any>;
@Input('optionsList') optionsList:any[]=[];
...
}
Then, in a parent component I have a template that contains the format for render each item, and send it to the list-box component for the task:
In the parent.component.html
<ng-template let-option pTemplate="item" #item>
<label>{{it}}: {{option.name}}</label>
</ng-template>
<app-list-box
[optionsList]="[{'name': '...'}, ...]"
[item]="item">
</app-list-box>
This code obviously doesn't work, it shows the error that option
and it
don't exist in the parent.
The question is, How can I send a particular format to render each item in the child component?.
I can use a specific format in the child component, but if the list of items has other type of items with different fields, then the list-box component is not useful, and I would need to create another specific component or map the content from the list to set the names of the required fields, but it is not desired.
P.S. For this writing, I simplified the code using ngfor, because in practical terms it is what I require. I don't want to put the ngFor in the parent to set all the items there, the sample code is a simulation of an imported module that I want to customize.
Taking into account the following code:
parent.component.html:
<ng-template let-option pTemplate="item" #item>
<label>{{it}}: {{option.name}}</label>
</ng-template>
<app-list-box
[optionsList]="[{'name': '...'}, ...]"
[item]="item">
</app-list-box>
✓ I can see that the parameter let-option
is implicit, this is because it is not being assigned to a specific element of the context. (example: let example="something"
) [Valid]
🗙 The variable "it" has not been defined, which can generate an error. [Invalid]
Taking into account that {{ it }} means the current position of the loop, can be done as follows:
parent.component.html:
<ng-template let-option let-it="index" #item>
<label>{{it}}: {{option.name}}</label>
</ng-template>
<app-list-box
[optionsList]="[{'name': '...'}, ...]"
[item]="item">
</app-list-box>
list-box.component.html:
<div *ngFor="let option of optionsList; let i = index">
<ng-container *ngTemplateOutlet="item; context: {$implicit: option, index: i}"></ng-container>
</div>
It is important to note that:
$implicit -> will be assigned to let-option
index -> will be assigned to let-it
Test demo: https://codesandbox.io/s/elegant-sea-diiu5x?