Home > other >  Subscribe to all control values within an dynamic array of controls
Subscribe to all control values within an dynamic array of controls

Time:11-03

I have a dynamic array of ng-select controls. Each control represented by class NgSelectComponent.

When select value changes I want to subscribe to all controls.

Template

  <ng-select #select">
    <ng-option *ngFor="let option of options" [value]="select.id">{{ option.name }}</ng-option>
  </ng-select>

Class

  @ViewChildren('select') controls: QueryList<NgSelectComponent>;

  ngAfterViewInit() {
    concat(this.controls.toArray()).subscribe(x => {
      console.log(x);
    });
  }

I try that, but does not work.

concat(this.components.toArray()).subscribe(x => {
  console.log(x);
});

I believe it does not work because I had to subscribe to the values produced by each control corresponded by changeEvent but struggling to do that.

Any ideas how to solve?

CodePudding user response:

First of all, concat will likely not work. With concat, each observable in the array will wait for the previous to complete. This is probably not the behaviour you are expecting here.

You may use merge which will simply forwards all the emitted values to the output Observable individually. Or use combineLatest if you want an array of all the current values, whenever one Observable emits.

To convert the valueChanges of the controls to an array, use a map.

merge(
  ...this.controls.toArray().map(c => c.changeEvent.asObservable())
).subscribe(x => {
  console.log(x);
});

CodePudding user response:

This is what Reactive Forms are for. You create a FormArray and have FormControls in there. Then you can subscribe to the valueChanges observable of the FormControls. I highly recommend you to rewrite the code using this angular feature.

That being said, the easiest and more let's say unrefined solution is to use the changeEvent as you said:

<ng-select #select (change)="selectChanged($event)">
    <ng-option *ngFor="let option of options" [value]="select.id">{{ option.name }}</ng-option>
  </ng-select>
selectChanged($event) {
  // This function is called every time any select is changed.
  // If you want, you can create a Subject and .next() the values there to have an Observable
  console.log($event.target.value);
}
  • Related