级联下拉填充方法在Angular 7中运行多个 [英] Cascading dropdown fill method running more than one in Angular 7

查看:69
本文介绍了级联下拉填充方法在Angular 7中运行多个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Stackblitz

解决方案

使用吸气剂时,这种情况会在组件的整个寿命中发生多次.

您必须更改方法.一种方法是订阅表单的valueChanges,然后更改订阅中的状态".像

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>

您的分叉的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>

分叉的stackblitz

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

解决方案

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

这篇关于级联下拉填充方法在Angular 7中运行多个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆