cbutler
cbutler

Reputation: 933

Angular passing props to child not updating

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

Answers (2)

James
James

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

Shashank Vivek
Shashank Vivek

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

Related Questions