简体   繁体   中英

angular4 change detection update all components inside ngfor

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>

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM