I have 2 components:
x-list-component and xcomponent.
x-list-component uses the *ngfor='let VAR of array' directive to create a list of xcomponent and pasts VAR as an input to xcomponent.
<xcomponent [VAR]='VAR'></xcomponent>
xcomponent uses interpolation in the template to render the passed VAR inside a div. {{VAR.args}}
Everything is ok but when changedetection occurs inside one instance of xcomponent the view is rerendered and the new value of VAR.args appears by all the others xcomponents instead of only on the xcomponent which modified his VAR.args.
so I want to know how I can only updates the view of the xcomponent which emitted the change detection and keep the state of others xcomponents unchanged.
//list component and his template
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-kameroke-list',
templateUrl: './kameroke-list.component.html',
styleUrls: ['./kameroke-list.component.css']
})
export class KamerokeListComponent implements OnInit {
lyrics=[{"first":"paroles","second":"paroles2","third":"paroles3","id":"test"},
{"first":"lyrics","second":"lyrics2","third":"lyrics3","id":"secondTest"}
];
constructor() { }
ngOnInit() {
}
}
<!--template for list-component-->
<app-kameroke *ngFor="let lyric of lyrics" [first]="lyric.first" [second]="lyric.second" [third]="lyric.third"></app-kameroke>
<!--attribuer un id dynamiquement : [attr.id]="lyric.id"-->
//kamerokeComponent and his template
import { Component, OnInit , Input ,ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'app-kameroke',
templateUrl: './kameroke.component.html',
styleUrls: ['./kameroke.component.css']
})
export class KamerokeComponent implements OnInit {
@Input() url:string;
@Input() private first:string;
@Input() private second:string;
@Input() private third:string;
masked:boolean=true;
playing:boolean=false;
widget :any;
lyrics:object;
constructor(private ref:ChangeDetectorRef) {
}
ngOnInit() {
//all this event in insertFrame
this.lyrics={
1:"ca marche",
2:"ca cartonne",
3:"c le feu",
4:"testons voir"
};
this.widget=window['SC'].Widget(document.getElementById("test"));
this.widget.bind(window['SC'].Widget.Events.PLAY,()=>{this.playing=true});
this.widget.bind(window['SC'].Widget.Events.PAUSE,()=>{this.playing=false});
this.widget.bind(window['SC'].Widget.Events.FINISH,()=>{this.playing=false});
this.widget.bind(window['SC'].Widget.Events.PLAY_PROGRESS,()=>{
this.widget.getPosition(
(time)=>{
//TODO set les variables first second and third
if(this.lyrics){
let timing=Math.ceil(time/1000);
//console.log(this.lyrics[timing]);
if(this.lyrics[timing]){
console.log(timing);
this.first=this.lyrics[timing];
this.second=this.lyrics[timing];
this.third=this.lyrics[timing];
this.ref.detectChanges();
}
}
}
);
});
}
hide(){
this.masked=false;
}
}
<!--kamerokeComponent template-->
<div class="container">
<div class="row">
<div class="col-sm soundcloudCol">
<iframe (load)="hide()" id="test" allow="autoplay" width="100%" height="100%" scrolling="no" frameborder="no"
src="https://w.soundcloud.com/player/?url=https://soundcloud.com/maahlox/la-vie-cest-la-bastonde&{ ADD YOUR PARAMETERS HERE }">
</iframe>
</div>
</div>
<div class="row lyrics" [hidden]="masked" >
<div class="col-sm">
<br><br>
<p class="first">{{first}}</p>
<p class="second">{{second}}</p>
<p class="second">{{third}}</p>
</div>
</div>
</div>
It is because on your ngOnInit
you are getting the element by id from the hard-coded value "test"
. Then for all your kamerokeComponent
components there will be only one widget element. So when you change that all of your kamerokeComponent
values will get changed. I suggest to pass the id
of the element as well.
// template for list-component
<app-kameroke *ngFor="let lyric of lyrics" [first]="lyric.first"
[second]="lyric.second" [third]="lyric.third" [id]="lyric.id"></app-kameroke>
//kamerokeComponent
import { Component, OnInit , Input ,ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'app-kameroke',
templateUrl: './kameroke.component.html',
styleUrls: ['./kameroke.component.css']
})
export class KamerokeComponent {
@Input() url:string;
@Input() private first:string;
@Input() private second:string;
@Input() private third:string;
@Input() private id:string;
masked:boolean=true;
playing:boolean=false;
widget :any;
lyrics:object;
constructor(private ref:ChangeDetectorRef) {
}
ngAfterViewInit() {
//all this event in insertFrame
this.lyrics={
1:"ca marche",
2:"ca cartonne",
3:"c le feu",
4:"testons voir"
};
this.widget=window['SC'].Widget(document.getElementById(this.id));
this.widget.bind(window['SC'].Widget.Events.PLAY,()=>{this.playing=true});
this.widget.bind(window['SC'].Widget.Events.PAUSE,()=>{this.playing=false});
this.widget.bind(window['SC'].Widget.Events.FINISH,()=>{this.playing=false});
this.widget.bind(window['SC'].Widget.Events.PLAY_PROGRESS,()=>{
this.widget.getPosition((time)=>{
//TODO set les variables first second and third
if(this.lyrics){
let timing=Math.ceil(time/1000);
//console.log(this.lyrics[timing]);
if(this.lyrics[timing]){
console.log(timing);
this.first=this.lyrics[timing];
this.second=this.lyrics[timing];
this.third=this.lyrics[timing];
this.ref.detectChanges();
}
}
});
});
}
hide(){
this.masked=false;
}
}