Reputation: 933
I am trying to pass an object down to a child component as a prop. The object starts as null and gets set when a user selects an item from the list. What's strange is that the object gets set correct the first time but not after.
Here is my parent component:
@Component({
selector: 'my-app',
template: `
<div>
<search-bar (submitted)="onSearch($event)"></search-bar>
<div>
<video-detail [video]="selectedVideo"></video-detail>
<video-list [videos]="videos" [onVideoSelect]="onVideoSelect" ></video-list>
<div>
</div>
`
})
export default class AppComponent {
videos = [];
selectedVideo = null;
constructor(private youtube: YoutubeService) { }
onSearch(searchTerm: string) {
this.youtube.search(searchTerm).subscribe((response) => {
this.videos = response.items;
this.selectedVideo = response.items[0];
});
}
// called when the user clicks an item
onVideoSelect(video: object) {
this.selectedVideo = video;
}
}
Child component:
const { Component, Input } = ng.core;
const { DomSanitizer } = ng.platformBrowser;
@Component({
selector: 'video-detail',
template:
`
<ng-container *ngIf="video; else loading">
<div>
<div>
<iframe title="video player" [src]="getVideoSrc()"></iframe>
</div>
<div>
<h4 [innerHTML]="video.snippet.title"></h4>
<p [innerHTML]="video.snippet.description"></p>
</div>
</div>
</ng-container>
<ng-template #loading>
<div>
No Video Selected.
</div>
</ng-template>
`
})
export default class VideoDetailComponent {
@Input() video = null;
constructor(public sanitizer: DomSanitizer) { }
getVideoSrc() {
const videoSrc = this.sanitizer.bypassSecurityTrustResourceUrl(`https://www.youtube.com/embed/${this.video?.id?.videoId}`);
return videoSrc;
}
}
Any idea what I'm doing wrong?
Upvotes: 4
Views: 4404
Reputation: 2895
When you pass objects as @Inputs()
into children, Angular only begins change detection when the object reference has changed.
Therefore when you update the object, it needs to be a new reference in order for your child component to act on it.
Try using
this.selectedVideo = Object.assign({}, response.items[0]);
This will create a new object each time so angular will pick up the change.
Upvotes: 6
Reputation: 17504
You need to create a new object and pass as @Input
so that the angular can identify the change.
Try
onSearch(searchTerm: string) {
this.youtube.search(searchTerm).subscribe((response) => {
this.videos = response.items;
this.selectedVideo = JSON.parse(JSON.stringify(response.items[0])); // <-- here
});
}
Upvotes: 2