0
votes

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&amp;{ 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>
1
Can you please include your code in the question - Senal
i added the code dear - Anicet Nge

1 Answers

0
votes

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;   
   }
}