Boanta Ionut
Boanta Ionut

Reputation: 402

Angular 2 Reactive Forms only get the value from the changed control

I have a dynamically created form with all inputs. I am subscribing for changes, but when a control is changed I get the values from all the controls, so I don't really know which one is changed. Is it possible to get the changed value only from the changed control with the valueChanges function?

The form is pretty big, so subscribing every control to valueChanges is not an option.

The function currently looks like this:

checkForValueChanges() {
    this.metadataForm.valueChanges.subscribe(controls => {
        // how to get the changed control form name here ?
    });
}

Since the project is really big, I just made a simple example to show my issue: StackBlitz example You can see in console that the result I get is all of the controls instead of just the one it's changed.

Upvotes: 2

Views: 5398

Answers (2)

Alexander Zhukov
Alexander Zhukov

Reputation: 86

this.imagSub = this.imagingForm.valueChanges.pipe(
    pairwise(),
    map(([oldState, newState]) => {
      let changes = {};
      for (const key in newState) {
        if (oldState[key] !== newState[key] && 
            oldState[key] !== undefined) {
          changes[key] = newState[key];
        }
      }
      return changes;
    }),
    filter(changes => Object.keys(changes).length !== 0 && !this.imagingForm.invalid)
  ).subscribe(
    value => {
      console.log("Form has changed:", value);
    }
  );

That subscription became active on ngOnInit and download some data from API (and after that put them into a form field, so I don't need first value [and value == undefined], because of form setting fields by herself)

For me, that solution works fine. But I guess if you have a form with "that has a huge amount of fields", this method will be even worse than saving subscriptions.

Upvotes: 4

ibenjelloun
ibenjelloun

Reputation: 7713

The cleanest way I can imagine is to subscribe dynamicaly to all the form controls :

const subscriptions = [];
for (const key of Object.keys(this.metadataForm.controls)) {

    const subscription = this.metadataForm.controls[key].valueChanges
    .subscribe(value => console.log('value :' + value[key] + ' and key : ' + key));

    subscriptions.push(subscription);
}

I added an array of subscriptions to handle the unsubscribe on destroy.

Upvotes: 5

Related Questions