rakibtg rakibtg - 19 days ago 6
Javascript Question

ng2 - passing information from siblings component directives

I am learning Angular 2 by creating simple projects, here is the Plunker of the app.

It has two custom made components,


  1. video-list.ts

  2. video-player.ts



Both of the above components are displayed in the
app.ts
compontent using their directives.

The video player component should show any clicked song as the
{{ nowPlaying }}
variable, as the list of song are in the video-list component i can't understand how to pass the clicked song item and display its title on the video-player component.

Though, video player component has a
@Input
decorator for the
nowPlaying
object variable but i have no idea how to reach the selected object via the app component from the video list component.

I also added a
nowPlayingDefault
variable in the app component to pass it to the video player component by default.

Here is the code: (https://plnkr.co/edit/Tt0zLudPqhrBfG0iffj1)

app.ts

// root app component
import {Component, NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { VideoList } from './video-list';
import { VideoPlayer } from './video-player';

@Component({
selector: 'my-app',
template: `
<div class='block'>
<h2>Hello {{name}}</h2>
<video-player [nowPlaying]='nowPlayingDefault'></video-player>
<hr>
<video-lists></video-lists>
</div>
`,
})
export class App {
nowPlayingDefault:string = 'Please select a song.';
constructor() {
this.name = 'Angular2'
}
}

@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [
App,
VideoList,
VideoPlayer
],
bootstrap: [ App ]
})
export class AppModule {}


video-list.ts

import { Component } from '@angular/core';

@Component({
selector: 'video-lists',
template: `
<div id='video-lists' class='block'>

<div style='text-align: center;'>
From Video List Component
</div>

<a href='' style='display: block'
*ngFor='let item of items'
(click)='selectSong( item, $event )'>
{{ item.title }}
</a>

</div>
`
})

export class VideoList {
test: string = 'sos';
items = [
{
'title' : 'yo test',
'url' : '823ery783dh.mp3'
},
{
'title' : 'yall rappin',
'url' : '25wd13edc1.mp3'
}
];

selectSong( item, event )
{
event.preventDefault();
console.log( item );
}

}


video-player.ts

import { Component, Input } from '@angular/core';

@Component({
selector: 'video-player',
template: `
<div id='video-player' class='block'>
<div style='text-align: center'>~ Video Player Block ~ </div>
<div style='color: blue;'>{{ nowPlaying }}</div>
</div>
`
})

export class VideoPlayer {
@Input() nowPlaying: string = 'Please select a song.';
}


How can i display the clicked song title from video list component to the video player component's
nowPlaying
variable?

Answer

Add an @Output() to be able to notify

export class VideoList {
  @Output() selectedChange:EventEmitter = new EventEmitter();      

  test: string = 'sos';
  items = [
    {
      'title' : 'yo test',
      'url'   : '823ery783dh.mp3'
    },
    {
      'title' : 'yall rappin',
      'url'   : '25wd13edc1.mp3'
    }
  ];

  selectSong( item, event )
  {
    event.preventDefault();
    console.log( item );
    this.selectedChange.emit(item);
  }
}

and bind to the @Output() event and update a property when new values are emitted

@Component({
  selector: 'my-app',
  template: `
    <div class='block'>
      <h2>Hello {{name}}</h2> 
      <video-player [nowPlaying]='nowPlayingDefault'></video-player> 
      <hr>
      <video-lists (selectedChange)="nowPlaying=$event"></video-lists>
    </div>
  `,
})
Comments