0

I have a sample form which I do submit a data and edit the same by populating the same record in the Form where I developed the form using FormGroup and binding the values using form control API methods get().setvalue() for the text inputs but I am struggling in populating the DropDowns(select) in edit

I am using this line to populate the particular dropdown of the edit record as below

this.form.controls['p_county'].setValue(county[0].county_id, {onlySelf: true});

<form [formGroup]="form">
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label class="form-label">Country</label>
                <select class="form-control" formControlName="p_country">
                <option *ngFor="let element of country" [value]="element.country_id">{{element.country_name}}</option>
              </select>
                <span class="text-danger" *ngIf="f.p_country.touched && f.p_country.errors?.required">Please Select Country</span>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label class="form-label">State</label>
                <select formControlName="p_state" class="form-control" name="p_state">
                <option *ngFor="let element of state" [value]="element.state_id">{{element.state_name}}</option>
              </select>
                <span class="text-danger" *ngIf="f.p_state.touched && f.p_state.errors?.required">Please Select
                State</span>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label class="form-label">City</label>
                <select class="form-control" formControlName="p_city">
                <option *ngFor="let element of city" [value]="element.city_id">{{element.city_name}}</option>
              </select>
                <span class="text-danger" *ngIf="f.p_city.touched && f.p_city.errors?.required">Please Select City</span>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label class="form-label">County</label>
                <select class="form-control" formControlName="p_county">
                <option *ngFor="let element of county" [value]="element.county_id">{{element.county_name}}</option>
              </select>
                <span class="text-danger" *ngIf="f.p_county.touched && f.p_county.errors?.required">Please Select
                County</span>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label class="form-label">Zip Code</label>
                <input formControlName="p_zipcode" type="text" class="form-control" placeholder="Zip Code">
                <span class="text-danger" *ngIf="f.p_zipcode.touched && f.p_zipcode.errors?.required">Please enter Zip
                Code.</span>
            </div>
        </div>

    </div>
    <div style="text-align: center;">
        <button class="btn btn-primary" type="submit" (click)="addCompany()">Submit</button>
    </div>
</form>
      </div>

I initialize form as below,

    form = new FormGroup({
    p_county: new FormControl('', Validators.required),
    p_country: new FormControl('', Validators.required),
    p_city: new FormControl('', Validators.required),
    p_state: new FormControl('', Validators.required),
    p_zipcode: new FormControl('', Validators.required),
    //usr_lname:new FormControl('', [Validators.required, Validators.email]),
  });

My functionality is here

getDDlistName(listname: string) {
    this.ddlist.getDDlist(listname).subscribe(response => {
      if (response.success) {
        this.ddlistname = response.data;
      } else {
        this.router.navigate(['/error']);
      }
    });
  }

  getStateDDList(code: string) {
    this.ddlist.stateDropDown(code).subscribe(response => {
      if (response.success) {
        this.state = response.data;
      }
      else {
        this.toastr.info('NO DD Data')
      }
    });
  }

  getCityDDList(code: string) {
    this.ddlist.cityDropDown(code).subscribe(res => {
      if (res.success) {
        this.city = res.data;
      } else {
        this.toastr.info('NO DD data', 'Client')
      }
    })
  }

  getCountyDDList(code: string) {
    this.ddlist.countyDropDown(code).subscribe(res => {
      if (res.success) {
        this.county = res.data;
      } else {
        this.toastr.info('NO DD data', 'Client')
      }
    })
  }

  getCountryDDList(code: string) {
    this.ddlist.countryDropDown(code).subscribe(res => {
      if (res.success) {
        this.country = res.data;
      } else {
        this.toastr.info('NO DD data', 'Client')
      }
    })
  }

  addCompany() {
    console.log('form', this.form)
    if (this.form.valid) {
      this.isSubmitted = true;
      this.gc.addCompany(JSON.stringify(this.form.value)).subscribe(response => {
        if (response.success) {
          if (this.form.controls['p_active'].value == false) {
            this.toastr.success('DeActivated Successfully', 'Client');
          }
          this.toastr.success('Saved Successfully', 'Client');
          this.router.navigate(['/default/adduser/search']);
          this.form.reset();
        }
        else {
          this.isSubmitted = false;
          this.toastr.error(response.errorMessage, 'Client');
        }
      });
    } else {
      // this.isSubmitted = false;
      this.toastr.error('Required Field information is not available. Please enter required information in highlighted fields as below.');
      this.validateAllFormFields(this.form);
    }
    return;
  }

  getCompanies() {
    this.getDDlistName("Company_Type");
    this.getStateDDList('ST');
    this.getCityDDList('CT');
    this.getCountyDDList('CY');
    this.getCountryDDList('CNT');
    let obj = localStorage.getItem('currentuser');
    this.allCompanies.p_comp_id = JSON.parse(obj).comp_id;
    this.allCompanies.p_level = 2;
    this.allCompanies.p_usr_id = JSON.parse(obj).usr_id;
    this.gc.getCompanies(this.allCompanies).subscribe(response => {
      if (response.success) {
        let data = response.data.filter(value1 => {
          if (parseInt(value1.comp_id) == parseInt(this.url[4])) {
            return value1;
          }
        });
        let type = this.ddlistname.filter(response => {
          if (response.dd_det_id == data[0].comp_type) {
            return response;
          }
        });

        let city = this.city.filter(value => {
          if (value.city_name == data[0].city_name) {
            return value;
          }
        })
        let county = this.county.filter(value => {
          if (value.county_name == data[0].county_name) {
            return value;
          }
        });

        let country = this.country.filter(value => {
          if (value.country_name == data[0].country_name) {
            return value;
          }
        });

        let state = this.state.filter(value => {
          if (value.state_name == data[0].state_name) {
            return value;
          }
        });
        this.form.get('p_zipcode').setValue(data[0].comp_zip);
        this.form.get('p_comp_address').setValue(data[0].comp_address);
        this.form.get('p_comp_address1').setValue(data[0].comp_address1);
        this.form.get('p_admin_pswd').setValue(data[0].usr_pswd);
        this.form.get('p_active').setValue(data[0].active);
        this.form.controls['p_state'].setValue(state[0].state_id, { onlySelf: true });
        //this.form.value.p_state = state[0].state_id;
        this.form.controls['p_comp_type'].setValue(type[0].dd_det_id, { onlySelf: true });
        //this.form.value.p_comp_type = type[0].dd_det_id;
        this.form.controls['p_city'].setValue(city[0].city_id, { onlySelf: true });
        //this.form.value.p_city = city[0].city_id;
        this.form.controls['p_country'].setValue(country[0].country_id, { onlySelf: true });
        //this.form.value.p_country = country[0].country_id;
        this.form.controls['p_county'].setValue(county[0].county_id, { onlySelf: true });
        //this.form.value.p_county = county[0].county_id;
        this.form.get('p_usr_id').setValue(JSON.parse(localStorage.getItem('currentuser')).usr_id);
      } else {
        this.toastr.error('Something went Wrong Pls Check System Admin', 'Client');
      }
    });
  }
3
  • Are you using reactive form or template driven form? Commented Apr 6, 2020 at 17:28
  • Reactive form @RBC9662 Commented Apr 6, 2020 at 17:40
  • I think you are on right way but getting an issue to set the value in template. So plese just check once again with template and set the value of select tag like [value]. Commented Apr 6, 2020 at 17:46

1 Answer 1

1

You have several issues from what I can see.

  1. You name your form form in your .ts file and in your html (<form [formGroup]="form">), but then you are referencing the form controls in your template using f. Unless you have a getter that you didn't share, that will cause you issues:
<!-- you need to reference `form.p_county.touched` instead of `f.p_county...` (unless you have a getter named `f`) -->
<span class="text-danger" 
  *ngIf="form?.p_country.touched && form?.p_country.errors?.required">
    Please Select Country</span>
  1. You have an async issue in your .ts. Your functions (getDDlistName(), getStateDDList(), getCityDDList(), getCountyDDList(), & getCountryDDList()) are all making asynchronous requests for their data. This means you have to wait for those to complete before trying to access the data they are setting.

For example, in your current code you have:

getCompanies () {
  this.getDDlistName("Company_Type");
  /* ... other code */
  this.gc.getCompanies(this.allCompanies).subscribe(response => {
  if (response.success) {
  /* ... other code */

  /* `this.ddlistname` is not guaranteed to have a value */
  let type = this.ddlistname.filter(response => {
    if (response.dd_det_id == data[0].comp_type) {
      return response;
    }
  });
  /* ... other code */
}

You need to change those functions to return their observable so you can wait for them to complete before calling this.gc.getCompanies

Change to something like this:

/* this needs to return the observable */
getDDlistName (listname: string) {
  return this.ddlist.getDDlist(listname)
    .pipe(
      /* use tap() to set `this.ddlistname` */
      tap(response => {
        if (response.success) {
          this.ddlistname = response.data;
        } else {
          this.router.navigate(['/error']);
        }
      })
    );
}

/* do the same for getStateDDList(), getCityDDList(), getCountyDDList(), & getCountryDDList() */

/* change this to wait for all the requests before requesting gc.getCompanies() */
getCompanies () {
    let obj = localStorage.getItem('currentuser');
    this.allCompanies.p_comp_id = JSON.parse(obj).comp_id;
    this.allCompanies.p_level = 2;
    this.allCompanies.p_usr_id = JSON.parse(obj).usr_id;

    /* these are all async, so you need to wait for them to complete */
    /* forkJoin() will only emit a value when _all_ requests have finished */
    forkJoin([
      this.getDDlistName("Company_Type"),
      this.getStateDDList('ST'),
      this.getCityDDList('CT'),
      this.getCountyDDList('CY'),
      this.getCountryDDList('CNT')
    ]).pipe(
      /* once complete, switch to your getCompanies observable */
      switchMap(arrayOfResults => {
        return this.gc.getCompanies(this.allCompanies)
      })
    ).subscribe(response => {
      /* Note: this value here is the value from your `this.gc.getCompanies(this.allCompanies)` observable */
      if (response.success) { 
        /* ... other code */   
  1. You are doing too much when trying to set your forms values to the new data. patchValue() is the function you want to use to update a form's value without clearing the other form values. Also, it looks like you are trying to set form values that you don't have (p_comp_address, p_comp_address1, p_admin_pswd). I am assuming you just didn't post those form fields in your question, but make sure you have all those form fields in your template.

Change your code to to set the values to look like this:

getCompanies () {
    forkJoin([/* other code */]).pipe(
      /* once complete, switch to your getCompanies observable */
      switchMap(arrayOfResults => {
        return this.gc.getCompanies(this.allCompanies)
      })
    ).subscribe(response => {
      if (response.success) {
        /* other code */

        let state = this.state.filter(value => {
          if (value.state_name == data[0].state_name) {
            return value;
          }
        });

        /* once you have your values, use `patchValue()` to set them all at once  */
        this.form.patchValue({
          p_country: county[0].county_id,
          p_state: state[0].state_id,
          p_city: city[0].city_id,
          p_county: county[0].county_id,
        });
        /* any other code you want */
      } else {
        this.toastr.error('Something went Wrong Pls Check System Admin', 'Client');
      }
    });
  }

You may not need the [compareWith] function since you are setting your [value] to a string. But it couldn't hurt to keep it there.

Sign up to request clarification or add additional context in comments.

16 Comments

Thanks for the response @DJ House my requirement is I have a grid which contains some record where I will edit the record by clicking on edit button in the grid, however I used get('myname').setvalue() to fill the form for text fields but when it comes to dropdown, one of my array which receives values from API and it is not binding to the value in select option, For add it is binding if I want the dropdown for the edit record it is not
You may need to post more of your code in your question and/or provide a minimum repo that reproduces the issue you are seeing (like stackblitz.com). I’m having difficulty understanding where the exact problem could be.
I am guessing the issue could be a few different things. It could be the way you are binding to the select (using [value] or [ngValue]), how you are setting your select's option values (*ngFor), your [compareWith] function, how you are programmatically setting your select's value, or a combination of those.
My need is to do call this.gc.getcompanies after forkjoin
Ahh, I see. That is what the switchMap does (see docs). The sequence goes like this: after the forkJoin observable completes, switchMap switches the observable to this.gc.getcompanies(...). So the value in your subscribe() is the value returned from this.gc.getcompanies(...). Does that make sense? You are switching observables.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.