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

22,580

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);
        });
}
})
Share:
22,580

Related videos on Youtube

Talk is Cheap Show me Code
Author by

Talk is Cheap Show me Code

I do programming in Angular, Java and JavaScript. A movie freak and love to talk a lot. I really adore the StackOverflow community and proud to be part of it. Cheers.

Updated on May 30, 2021

Comments

  • Talk is Cheap Show me Code
    Talk is Cheap Show me Code almost 3 years

    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.

    • mayur
      mayur about 6 years
      Please add the relevant code to your query. Its to confusing whats your actual query is due to extra stuff.
    • Eliseo
      Eliseo about 6 years
      Not put the code in ngOnInit, just AFTER your line: this.form = new FormGroup(formGroup). Well, for clarity, create a function and call it after the line
    • Eliseo
      Eliseo about 6 years
      "Now I want to change the value of one form field based on changes on previous form fields". Well, think if the value must belong to the form or not.e.g. if your "field" formattedMessage is "My ChangeValue"+input1.value, you can not have this "field", just a < span>{{"My change Value "+form.getControl('input1').value}}< /span>
    • Talk is Cheap Show me Code
      Talk is Cheap Show me Code about 6 years
      @mayur : This is the actule code snippt to make you understand the whole scenario. Nothing here is extra.
  • Talk is Cheap Show me Code
    Talk is Cheap Show me Code about 6 years
    When I do this . it gives me two errors, ERROR TypeError: Cannot read property 'subscribe' of undefined at AddComponent.ngOnInit and Cannot read property 'next' of undefined at SafeSubscriber , So should I need to defined this.formCreated somewhere? IF so, how?
  • Eliseo
    Eliseo about 6 years
    @Manzur Khan, You needn't create a formCreated submited. just, after create the form (is a sync function), create the subscription to valueChanges
  • Talk is Cheap Show me Code
    Talk is Cheap Show me Code about 6 years
    @Eliseo , I am checking with your approach.
  • Talk is Cheap Show me Code
    Talk is Cheap Show me Code about 6 years
    @Manzur Khan, I created one common shared service which holds the value as true after form is created like this. this.form = new FormGroup(formGroup); this.dataService.change_current_form_created("true"); where this.dataService is commong service I am using to pass the messages to diff. components. Now I am able to log the value change event in the console but Getting only message like this, My changed values for is ${val}.'; and not the value itself.
  • Talk is Cheap Show me Code
    Talk is Cheap Show me Code about 6 years
    @Manzur Khan, Please orovide correct defination or declaration of Formcreated, (In my case I created an behaviour, observable subject). So that I can mark your answer as correct.
  • Talk is Cheap Show me Code
    Talk is Cheap Show me Code about 6 years
    @Eliseo , I tried your suggestion and it also worked fine. earlier I did the same but I was doing out side of http.call and hence as Manzur said, it was going out of the sync.
  • Manzur Khan
    Manzur Khan about 6 years
    @Jaydeep Glad you found it helpful, I've updated the answer as per your suggestions