Search code examples
angulartypescripteventsangular-reactive-formseventemitter

how to get values on change event in dynamic angular forms?


On component.ts file I am fetching the form field values in json array like this and converting it to an FormGroup control like this. This is working perfectly fine.

    getJsonForm(){
      let base_url = 'example.org'
      let getform_query = '/Base/formfieldsgenerator_get';
      let getform_endpoint = base_url.concat(getform_query);

     this.AllFormData = [];

        this.http.get('getform_endpoint'.'?tabpgrpid='+this.tabpgrpid+'&tabgrpname='+this.tabgrpname+'&usertabgrpname='+this.usertabgrpname+'&moduleid='+this.moduleid+'&templateid='+this.templateid+'&all_mod_data='+this.all_mod_data,{headers: this.headers}).subscribe(
        res => { 
         this.AllFormData = res;

                // this array is used to iterate in html side
               this.newfdata[element] = [];
               this.newfdata[element]['properties'] = [];


   Object.keys(res['com'][element]['schema']['properties']).forEach(inputKey => {
                      this.newfdata[element]['properties'].push(res['com'][element]['schema']['properties'][inputKey]);

                });

            // this is used to create form controls and form groups

                this.objectProps = Object.keys(res['com'][element]['schema']['properties']).map(prop => { 

          return Object.assign({}, { key: prop} , res['com'][element]['schema']['properties'][prop]);
          });

   for(let prop of Object.keys(res['com'][element]['schema']['properties'])) {

          formGroup[prop] = new FormControl(res['com'][element]['schema']['properties'][prop].value || '', this.mapValidators(res['com'][element]['schema']['properties'][prop].validation));

                }
        });

      this.form = new FormGroup(formGroup);
          }); 
}

Now on components.html side I am using the array like this to generate the dynamic form. This is also working fine.

<form (ngSubmit)="custom_submit(form.value)" [formGroup]="form" >
         <div *ngFor="let input1 of newfdata[tabname].properties">   
                <ng-container *ngIf="input1.type=='string'">
                                <div>
                                     <mat-form-field>
                                     <input matInput  [formControlName]="input1.field_name" [id]="input1.field_name" type="text"  placeholder="{{input1.title}}">
                                     </mat-form-field>   
                                </div>
                            </ng-container>
         </div>  
</form>

Now I want to change the value of one form field based on changes on previous form fields. For that I am not able to subscribe to the valuechanges emitter of the form group variable.

I have tried this on ngOnit but it's not working and not producing any result in console.

ngOnit(){

   this.form.valueChanges.subscribe(val => {
                    this.formattedMessage = 'My changed values for is ${val}.';
                    console.log(this.formattedMessage);
                  });



}

Edit 1 :

After suggestion from Manzur Khan, I have passed the valueas true for the success of formcreated event and then in ngOnit used the value like this to get the onchange event :

      this.form = new FormGroup(formGroup);
      this.dataService.change_current_form_created("true");

and in NgonIt

this.dataService.last_form_craeted_message.subscribe(data => {
  if(data=="true") {
    this.form.valueChanges.subscribe(val => {
         this.formattedMessage = 'My changed values for is ${val}.';
            console.log(this.formattedMessage);
        });
}
});

Now I am able to log on change event in console but not able to get the resolution for ${val}.

Edit 2 :

Since the val is object, I was not able to resolve ${val} somehow,I Simply did

   this.form.valueChanges.subscribe(val => {
            console.log('the changed value is',val);
        });

It gives me all the values of given formgroups. I still need to optimize this result further so that I just listened to specific form controls. But it has give me a road to go. Thanks all.


Solution

  • It's happening because you are listening to value changes of the form even before the form is present(since it's inside async)

    You can try something like this

    First declare an Observable

    formCreated: Subject<boolean> = new Subject();
    

    Then in your form code

    this.form = new FormGroup(formGroup);
    this.formCreated.next(true)
    

    and then in your ngOnInit

    this.formCreated.subscribe(data => {
      if(data) {
        this.form.valueChanges.subscribe(val => {
             this.formattedMessage = 'My changed values for is ${val}.';
                console.log(this.formattedMessage);
            });
    }
    })