Reputation: 20734
My AppComponent's template (bootstraped in the AppModule) is
<div *myDir="let item of mySource">
My Directive #{{item}}
</div>
where mySource
is an object with list
property
mySource = { list: [1, 2, 3, 4, 5] };
So, replacing myDir
with ngFor
(*ngFor="let item of mySource.list"
) would give me
My Directive #1
My Directive #2
My Directive #3
My Directive #4
My Directive #5
I'm trying to implement myDir
in pair with myComponent
to provide a templated wrapper over ngFor
Angular core directive to be able to pass mySource
(instead of mySource.list
) and achive the same result. Of course, the final goal is much more complex, but I need to solve this task in terms of minimal example... What is done?
my.directive.ts
import { MyComponent } from './my.component';
@Directive({ selector: '[myDir][myDirOf]' })
export class MyDirective {
private source;
constructor(/* ... */) { }
@Input() set myDirOf(source) {
this.source = source;
}
ngOnInit() {
// dynamic wrapping with MyComponent
const templateView = this.templateRef.createEmbeddedView({});
const compFactory = this.resolver.resolveComponentFactory(MyComponent);
const componentRef = this.viewContainer.createComponent(compFactory, null, this.viewContainer.injector, [templateView.rootNodes]);
// passing MyDir params to Mycomponent's instance
componentRef.instance.source = this.source;
componentRef.instance.template = this.templateRef;
}
}
my.component.ts
@Component({
selector: 'app-my',
template: `
<div *ngFor="let item of source.list">
<ng-template
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{
item: item
}">
</ng-template>
</div>`
})
export class MyComponent implements OnInit {
source;
template;
constructor() { }
}
The problem is that I can't pass item
back to the host component's template, so currently I'm getting just 5 same lines containing "My Directive #" and {{item}}
doesn't work. Looks like something's wrong with MyComponent's ng-template
. It accepts the template
but won't pass the item
.
I created an editable DEMO with my current situation. Also, here's a simple diagram of what I need:
Upvotes: 1
Views: 639
Reputation: 214007
Use $implicit
to pass data to item
my.component.html
<div *ngFor="let item of source.list">
<ng-template
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{
$implicit: item
}">
</ng-template>
</div>
Your template
<div *myDir="let item of mySource">
My Directive #{{item}}
</div>
is equivalent to
<ng-template myDir let-item [myDirOf]="mySource">
<div>
My Directive #{{item}}
</div>
</ng-template>
but if template variable (let-item) doesn't have value then it takes $implicit
by default
<ng-template myDir let-item="$implicit" [myDirOf]="mySource">
<div>
My Directive #{{item}}
</div>
</ng-template>
See also
Upvotes: 1