Allow the user to control the view of the toggle component. Break the toggle component up into multiple composable components that can be rearranged by the app developer.
This video has a typo as shown below which kept me guessing where the toggled is defined. Checked the stackblitz to confirm which has correct one.
ngAfterContentInit { this.toggleButton.toggle(d).subscribe(() => {}) }
@Isaac is there a way to query content child component by a directive so that we could have access to its hosting component instance:
@ContentChild(ToggleOnDirective) toggleButton: ToggleButtonInterface
This way we could declare our own toggle-button like components.
<toggle (toggled)="showMessage($event)">
<toggle-on>On</toggle-on>
<toggle-off>Off</toggle-off>
<toggle-button-other appToggleButton></toggle-button-other>
</toggle>
Otherwise we would be limited to toggle predefined "sub components" and the only benefit would be being able to organize them in our view.
@chihab, I'm not sure what you're trying to do here. Where is this code?
@ContentChild(ToggleOnDirective) toggleButton: ToggleButtonInterface
Is that in the appToggleButton
directive? What are you expecting to show up in toggleButton
?
@Isaac my bad, ToggleOnDirective should be ToggleButtonDirective which is the selector in ContentChild.
Please consider this code:
export interface ToggleButtonInterface {
reset();
}
toggle-button-other.component.ts
@Component({
selector: 'toggle-button-other',
...
})
export class ToggleButtonOtherComponent implements ToggleButtonInterface {
...
reset() {
}
}
toggle-button-awesome.component.ts
@Component({
selector: 'toggle-button-awesome',
...
})
export class ToggleButtonAwesome implements ToggleButtonInterface {
...
reset() {
}
}
app.component.html
<toggle>
...
<toggle-button-other appToggleButton></toggle-button-other>
</toggle>
<toggle>
...
<toggle-button-awesome appToggleButton></toggle-button-awesome>
</toggle>
toggle.component.ts
...
@ContentChild(ToggleButtonDirective) toggleButton: ToggleButtonInterface
ngAfterContentInit() {
this.toggleButton.reset(); // the problem here is that we get ToggleButtonDirective instance, how to get the instance of the hosting component ?
}
...
The question is how to specify to ContentChild right above how to get ToggleButtonOtherComponent or ToggleButtonAwesome instance instead of ToggleButtonDirective instance without explicitly naming class name as we don't konw what to expect. How to query the component hosting ToggleButtonDirective ?
@chihab, I don't think you can do exactly what you want.
One possible workaround is to have the two types of buttons extend
a parent class and then inject that parent class.
Another option is to use template references in your template:
<toggle-button-other appToggleButton #mybutton></toggle-button-other>
And use that string to find the button:
@ContentChild('mybutton') toggleButton: ToggleButtonInterface
More info: https://blog.angularindepth.com/handle-template-reference-variables-with-directives-223081bc70c2
Perhaps a dumb question, but is
@ContentChild
meant to be used with a component that has an <ng-content></ng-content>
template?
Not dumb. Yes @ContentChild
gives a component a way to access items that are placed inside of its <ng-content></ng-content>
area.
There's a problem with querying for the toggle-button using ContentChild
. In essence the query is not "live. so whenever the toggle-button is destroyed and recreated, the toggle component breaks.
Here's a demo of the problem: https://stackblitz.com/edit/adv-ng-patterns-02-compound-components-problem?file=app%2Fapp.component.html
Try unchecking then checking the "Create/destroy ToggleButton". And then use the toggle button. The component is broken.
I had a go at fixing it using ContentChildren
and a dose of observables. See here: https://stackblitz.com/edit/adv-ng-patterns-02-compound-components-fixed
My solution is "ok" but considerably more code. Not sure there is any simpler solution - what do you think?
just watched the next video. much better solution than trying to orchestrate things from the parent. Solves the problem I identified with much less code than my solution - nice