let's assume I have the following component:
@Component({
selector: 'todo-lib',
template: `
<li *ngFor="let todo of libService.todos">
<div class="view">
<label>{{todo.title}}</label>
<ng-container *ngTemplateOutlet="incomingTemplate;context:ctx"></ng-container>
</div>
</li>
<ng-template #incomingTemplate let-service="templateService">
<button (click)="service.removeTodo(todo)">delete</button>
</ng-template>
`,
styles: []
})
export class TodoLibComponent implements OnInit {
ctx = {
templateService: this.libService
};
The list of todos is inside the libService. I don't publish it here, since its logic doesn't matter. The "ng-template" will be injected from another component and will add a delete button to my todo list. That means: Typically there is no delete option, except the "ng-template" will be provided
However, this approach will fail with the following error:
message: "_v.context.todo is undefined"
since "todo" is not part of the context object 'ctx' I can't access it. To achieve this I would be forced to do it like this:
<ng-container *ngTemplateOutlet="incomingTemplate;context:{ todo: todo}">
This would let me access the todo object but not the service anymore.
It seems that I can't access the 'todo' property defined by the ngFor AND the service defined in the 'ctx' property at the same time. Is there a solution to achieve both?
Cheers
I also mentioned that on the official github repository of Angular. The correct answer by the devs was:
@dawidgarus: You can do:
<ng-container *ngTemplateOutlet="incomingTemplate;context:{ todo: todo, templateService: libService }">
In addition:
@dawidgarus suggestion is a good one and follows how scoping works in current Angular - I don't think we want to re-visit it. The only thing I would suggest is to use
<ng-template>
element instead of <ng-container>
as it generates less code, doesn't create unnecessary comment nodes in the DOM etc.:
<ng-template [ngTemplateOutlet]="incomingTemplate" [ngTemplateOutletContext]="{ todo: todo, templateService: libService }">
so I used ng-template instead of ng-container.
Cheers