级联下拉填充方法运行多于Angular7

Cascading dropdown fill method running more than one in Angular 7

我有一个 angular 应用程序。我在下面的示例中使用了级联组合框(国家/地区)。但是,get states()方法在state.component.ts运行宁了很多时间。这可能是什么原因?我只想 运行 只更改国家/地区选择。我放了debugger。您可以通过使用 F12 打开控制台来重现错误。 如果我的方法有误,我可以完全改变我的方法。

Stackblitz

当您使用 getter 时,这种情况会在组件的整个生命周期内发生多次。

你必须改变你的做法。一种方法是订阅表单的valueChanges,并在订阅中更改"states"。有些喜欢

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) { }
}

您component.html必须参考_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>

你的forked stackblitz

更新 好吧,从整个问题的角度来看,也许是时候创建一个组件来控制国家和州了。它更复杂一些,因为我们必须使用 viewProviders 和 FormGroupDirective。

想法,将控件的名称(countryID 和 StateID)和控件的标签(countryLabel 和 stateLabel)作为参数传递给组件

新组件变为

@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;
  }
}

.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>

以及使用

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

forked stackblitz