8

I want to know what purpose the context parameter serves in createEmbeddedView() method in Angular. The online angular docs do not provide this information.

For example I was reading this code where the author has made an iterator structural directive.

    import {
    Directive, ViewContainerRef, TemplateRef, Input, SimpleChange
} from "@angular/core";

@Directive({
    selector: "[paForOf]"
})

export class PaIteratorDirective {
    constructor(private container: ViewContainerRef, private template: TemplateRef<Object>) {
    }

    @Input("paForOf") dataSource: any;

    ngOnInit() {
        this.container.clear();
        for (let i = 0; i < this.dataSource.length; i++) {
            this.container.createEmbeddedView(this.template, new PaIteratorContext(this.dataSource[i]));
        }
    }
}

class PaIteratorContext {
    constructor(public $implicit: any) { }
}

This is shown on the checkbox checked event on the template like this:

    <div class="checkbox">
    <label><input type="checkbox" [(ngModel)]="showTable" />Show Table</label>
</div>
<table *paIf="showTable" class="table table-sm table-bordered table-striped">
    <tr>
        <th></th>
        <th>Name</th>
        <th>Category</th>
        <th>Price</th>
    </tr>
    <template [paForOf]="getProducts()" let-item>
        <tr>
            <td colspan="4">{{item.name}}</td>
        </tr>
    </template>
</table>

I want to understand this code:

this.container.createEmbeddedView(this.template, new PaIteratorContext(this.dataSource[i]));

Why i need to create an object of PaIteratorContext() class? why i can't just do this:

this.container.createEmbeddedView(this.template, this.dataSource[i]);

Please help ?

yogihosting
  • 5,494
  • 8
  • 47
  • 80

2 Answers2

12

When you define a template you can have input parameters specified through let-paramname:

<template [paForOf]="getProducts()" let-item='item'>
     <span>{{item.name}}</span>
</template>

The context object is what allows you to pass those parameters to the template when creating it.

this.container.createEmbeddedView(this.template, {item: {name: 'John'}}`

Why i need to create an object of PaIteratorContext() class? why i can't just do this:

You don't have to create an instance of the PaIteratorContext, you just have to pass an object with the name property in that particular case. So the following will work as well:

this.container.createEmbeddedView(this.template, { $implicit: this.dataSource[i] });

If the input property is specified like this let-item without second part =something, the embedded view treats it as let-item=$implicit so you have to pass a context object with $implicit property.

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • OK, why i have to use new PaIteratorContext() and then pass them on it? what's the purpose of this class - PaIteratorContext() here? – yogihosting Oct 24 '17 at 12:38
  • @yogihosting, you don't have to create an instance of the class, you just have to pass an object with properties relevant to the ones specified with `let-*` – Max Koretskyi Oct 24 '17 at 12:39
  • OK, if i pass them as object like this - this.container.createEmbeddedView(this.template, this.dataSource[i]); then why the code does not work? – yogihosting Oct 24 '17 at 12:42
  • Thank you $implicit does the work here - this.container.createEmbeddedView(this.template, { $implicit: this.dataSource[i] }); . I understood that $implicit is creating the appropriate property for the dataSource on runtime. – yogihosting Oct 24 '17 at 12:48
  • 1
    Thank you for excellent details, there was absolutely no information on this on the whole net until your answer came. – yogihosting Oct 24 '17 at 13:11
  • 1
    @yogihosting, you're welcome. Check out my blog, there's a lot of information there not available anywhere else – Max Koretskyi Oct 24 '17 at 13:13
1

If you pass {item: 'someValue'} then the stamped template can access the value using

<template let-foo="item"> 
  <div>{{foo}}</div>
</template>

or if you pass {$implicit: 'someValue'}

<template let-foo> 
  <div>{{foo}}</div>
</template>
yurzui
  • 205,937
  • 32
  • 433
  • 399
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567