在 Angular 7 中运行不止一种的级联下拉填充方法 [英] Cascading dropdown fill method running more than one in Angular 7

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

问题描述

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

Stackblitz

解决方案

当您使用 getter 时,这种情况会在组件的生命周期中发生多次.

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

导出类 StateComponent {_studentForm;//使用_studentForm@输入()set studentForm(value)//使用setter,当有值时订阅{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;状态:状态[];构造函数(私有选择服务:选择服务){}}

您的 component.html 必须引用 _studentForm

<选择 [formControlName]="id" ><option [value]="0">--选择--</option><option *ngFor="let state of states " value= {{state.id}}>{{state.name}}</option></选择></表单>

您的分叉的stackblitz

更新好吧,考虑到整个问题,现在是时候创建一个控制国家和州的组件了.这是一些更复杂的,因为我们必须使用 viewProviders 和 FormGroupDirective.

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

新组件变成了

@Component({选择器:'应用程序国家',视图提供者:[{提供:ControlContainer,useExisting: FormGroupDirective}],templateUrl: './country-state.component.html',styleUrls: ['./country-state.component.css']})导出类 CountryStateComponent 实现 OnInit、OnDestroy {@Input() countryID: 字符串;@Input() stateID: 字符串;@Input() countryLabel: 字符串;@Input() stateLabel: 字符串;_countryID:表单控件;//我们必须控制两个FormControl"_stateID:表单控件;//一个用于国家,一个用于声明状态:任何[] = [];国家:任何[] = [];isAlive: boolean = true;构造函数(私有选择服务:选择服务,私有 fgd: FormGroupDirective) { }ngOnInit() {//首先,我们得到国家this.countries = this.selectService.getCountries();//使用FormGroupDirective搜索"控件this._countryID = (this.fgd.form.get(this.countryID) as FormControl);this._stateID = (this.fgd.form.get(this.stateID) as FormControl);//我们订阅了valueChanges.我们使用典型"结构takeWhile"//当组件被销毁时取消订阅this._countryID.valueChanges.pipe(takeWhile(() => this.isAlive)). 订阅 (res => {this.states = this.selectService.filterStates(this._countryID.value);})}ngOnDestroy() {this.isAlive = false;}}

.html

{{countryLabel}}:<br/><!--请注意,我们使用的是 [formControl],而不是 [formControlName]--><选择[formControl]="_countryID"><option [value]="0">--选择--</option><option *ngFor="let country of countries" [value]="country.id">{{country.name}}</option></选择><br/>{{stateLabel}}:<br/><选择 [formControl]="_stateID" ><option [value]="0">--选择--</option><option *ngFor="let state of states " value= {{state.id}}>{{state.name}}</option></选择>

和用途

</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天全站免登陆