Cascading dropdown fill method running more than one in Angular 7

人走茶凉 提交于 2019-12-04 02:27:24

问题


I have an angular app. And I'm using cascading combobox (country-state) in below example. But, get states() method in state.component.ts running a lot of time. What can be the reason of this? I want run only country selection changed. I put debugger. You can reproduce bug by open console with F12. If my method mistake, I can change completely my way.

Stackblitz


回答1:


When you use a getter, this happens several times alog life of component.

You must change your aproach. One way is subscribe to valueChanges of the form, and change "states" in the subscribe. Some like

export class StateComponent  {
  _studentForm;  //Use a _studentForm
  @Input() 
  set studentForm(value)  //use a setter, to subscribe when has value
  {
     this._studentForm=value;
     this._studentForm.get(this.countryId).valueChanges.subscribe(res=>{
       var val = this._studentForm.controls[this.countryId].value;
       this.states=this.selectService.filterStates(val);
     })
  }
  @Input() id:string;
  @Input() countryId:string;
  states: State[];

  constructor(private selectService: SelectService) { }
}

You component.html must be reference to _studentForm

<form [formGroup]="_studentForm">
    <select [formControlName]="id" >
      <option [value]="0">--Select--</option>
      <option *ngFor="let state of states " value= {{state.id}}>{{state.name}}</option>
    </select>
</form>

Your forked stackblitz

Update Well, with the vision of the whole problem, perhafs it's time to create a Component that control country and states at time. it's some more complex beacuse we must use viewProviders and FormGroupDirective.

The idea, pass as argument to the component the name of the controls (countryID and StateID) and the label of the controls (countryLabel and stateLabel)

The new component becomes as

@Component({
  selector: 'app-country-state',
  viewProviders: [
    {
      provide: ControlContainer,
      useExisting: FormGroupDirective
    }
  ],
  templateUrl: './country-state.component.html',
  styleUrls: ['./country-state.component.css']
})
export class CountryStateComponent implements OnInit, OnDestroy {

  @Input() countryID: string;
  @Input() stateID: string;
  @Input() countryLabel: string;
  @Input() stateLabel: string;

  _countryID: FormControl;  //We must control two "FormControl"
  _stateID: FormControl;    //One for country and one for stated
  states: any[] = [];
  countries: any[] = [];

  isAlive: boolean = true;
  constructor(private selectService: SelectService,
    private fgd: FormGroupDirective) { }

  ngOnInit() {
    //first, we get the countries
    this.countries = this.selectService.getCountries();

    //"search" the controls using the FormGroupDirective
    this._countryID = (this.fgd.form.get(this.countryID) as FormControl);
    this._stateID = (this.fgd.form.get(this.stateID) as FormControl);
    //Our subscribe to valueChanges. We use a "tipical" contruction "takeWhile"
    //To unsubscribe when the compnent are destroyed
    this._countryID.valueChanges.pipe(
      takeWhile(() => this.isAlive)
    ).subscribe(res => {
      this.states = this.selectService.filterStates(this._countryID.value);
    })

  }
  ngOnDestroy() {
    this.isAlive = false;
  }
}

The .html

{{countryLabel}}:<br/>
<!--see that we use [formControl], NOT [formControlName]-->
<select [formControl]="_countryID">
      <option [value]="0">--Select--</option>
      <option *ngFor="let country of countries" [value]="country.id">{{country.name}}</option>
    </select>
    <br/>
{{stateLabel}}:<br/>
    <select [formControl]="_stateID" >
      <option [value]="0">--Select--</option>
      <option *ngFor="let state of states " value= {{state.id}}>{{state.name}}</option>
    </select>

And the use

<app-country-state 
    [countryID]="'countryId1'" [countryLabel]="'Student Country'"
    [stateID]="'stateId1'" [stateLabel]="'Student State'">
</app-country-state>

The forked stackblitz



来源:https://stackoverflow.com/questions/54073280/cascading-dropdown-fill-method-running-more-than-one-in-angular-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!