I'm using Angular 2.0.1.
I have a component that can take in any other component via <ng-content>
-- this works great.
The issue I run into is when I want to reference the injected component.
If I knew that <ng-content>
would only ever be one component I could say:
@ContentChild(MyComponent) dynamicTarget: IMyComponent;
but because it could be any component (the only assumption I would make is that any injected component implements a specific interface) it become trickier.
I've also tried <ng-content #dynamicTarget'>
and then referring to it by saying @ContentChild('dynamicTarget') dynamicTarget: IMyComponent;
but this returns undefined.
Does anyone know how I could tell Angular 2 that this thing is an instance of a component so that I can attempt to call a function on it?
To further clarify the use case -- I have a multi-step wizard that could take in any component as content, and I want to call the validate
function on the content (which again, I would assume exists on said instance)
One approach could be to give the same #id
to any dynamic component.
I've given #thoseThings
. (I think it's almost same as @Missingmanual)
PLUNKER (see console for the matches.)
@Component({
selector: 'my-app',
template: `
<div [style.border]="'4px solid red'">
I'm (g)Root.
<child-cmp>
<another-cmp #thoseThings></another-cmp>
</child-cmp>
</div>
`,
})
export class App {
}
@Component({
selector: 'child-cmp',
template: `
<div [style.border]="'4px solid black'">
I'm Child.
<ng-content></ng-content>
</div>
`,
})
export class ChildCmp {
@ContentChildren('thoseThings') thoseThings;
ngAfterContentInit() {
console.log(this.thoseThings);
this.validateAll();
if(this.thoseThings){
this.thoseThings.changes.subscribe(() => {
console.log('new', this.thoseThings);
})
}
}
validateAll() {
this.thoseThings.forEach((dynCmp: any) => {
if(dynCmp.validate)
dynCmp.validate(); // if your component has a validate function it will be called
});
}
}
@Component({
selector: 'another-cmp',
template: `
<div [style.border]="'4px solid green'">
I'm a Stranger, catch me if you can.
</div>
`,
})
export class AnOtherCmp {
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, Parent, Transcluded1, Transcluded2 ],
providers: [
{provide: TranscludedBase, useExisting: Transcluded1, multi:true}
{provide: TranscludedBase, useExisting: Transcluded2, multi:true}
],
bootstrap: [ App ]
})
Plunker example
You could use dynamic component creation Angular 2 dynamic tabs with user-click chosen components with wizard steps instead of tabs.
Another way is to pass the elements explicitly to an input in addition to projecting them:
Plunker example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With