Update:
Günter Zöchbauer provided a very acceptable answer that works perfectly (and thank you!). But I still have a question to check if what I am doing is the correct way of getting the result I seek. Context is given below.
What I expect with my custom tag on the parent view, is that when the *ngIf
condition is false, the component is not loaded at all (or maybe most part of it). Is it normal that even if it is not in the DOM (because the condition is false), it is still loaded? Is there a better way to embed components' templates (and the logic of their class) into a parent component's template?
I am new to Angular 2 and so far I'm having much fun developing a small song track metadata application based on the Spotify API.
TL;DR: How to init a component only when its corresponding HTML tag (defined with the selector
property of @Component
) if *ngIf="true"
?
But of course I'm facing difficulties! I have this component, TrackDetailComponent
, in the template of which I would like to include 2 other components. On clicking on a button, it would switch from one inner component to the other.
Here is how the template looks like (note that I only have developed one of the two inner components for now, so I used a placeholder in stead of the second one):
<div id="view">
<tig-track-info *ngIf="childView == TrackDetailView.InfoView" [track]="track"></tig-track-info>
<p *ngIf="childView == TrackDetailView.LyricsView">Here go the lyrics</p>
</div>
As you can see, my inner component (named TrackInfoComponent
) has an input parameter. Here is an excerpt of that component:
@Component({
selector: "tig-track-info",
templateUrl: "app/components/track-info/track-info.component.html",
styleUrls: ["app/components/track-info/track-info.component.css",
"app/shared/animations.css"]
})
export class TrackInfoComponent implements OnInit {
private _trackId: string = null;
@Input()
track: Track = null;
previewAudio: any = null; // The Audio object is not yet defined in TypeScript
albumArtworkLoaded: boolean = false;
...
}
My real problem is not embedding the TrackInfoComponent
inside the other one, but it is to sync them. The TrackDetailComponent
calls an API asynchronously and then initializes the track
property. But TrackInfoComponent
also needs that track
to be initialized in order to do its job or else I get a null reference exception (which is logical).
I tried setting the child component data in the ngOnInit()
and setting the *ngIf
of its parent's template to true only when the track
is ready but it seems that ngOnInit()
is called right away, even if the DOM element tig-track-info
is not display with *ngIf
.
I guess I could use events or my own init method in the child component, to call only when I'm ready, but I would like to know if there is a better way to do it using the Angular 2 component lifecycle hooks or any other method recommanded for that. Does anyone have any idea about that?
Thank you :-)
NgIflink. A structural directive that conditionally includes a template based on the value of an expression coerced to Boolean. When the expression evaluates to true, Angular renders the template provided in a then clause, and when false or null, Angular renders the template provided in an optional else clause.
angular - Component initialization by ngIf does not trigger ngOnInit - Stack Overflow. Stack Overflow for Teams – Start collaborating and sharing organizational knowledge.
Notice that the div element has an ngIf attribute. This attribute's value is the result of the contentVisible property. So if the contentVisible property is true, then the div element is created. Conversely, if the contentVisible property is false, then the div element is destroyed.
Your div will be rendered and visible once the change detection is triggered. When a change is detected, the whole lifecycle is ran again. If you want to run something, you should hook on one of the events of the lifecycle.
You can use OnChanges which is called whenever an @Input()
property value is changed by a template binding `[track]="..."
export class TrackInfoComponent implements OnChanges {
ngOnChanges(changes: SimpleChanges) {
if(this.track) {
...
}
}
}
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