级联下拉填充方法运行多于Angular7
Cascading dropdown fill method running more than one in Angular 7
我有一个 angular 应用程序。我在下面的示例中使用了级联组合框(国家/地区)。但是,get states()
方法在state.component.ts
运行宁了很多时间。这可能是什么原因?我只想 运行 只更改国家/地区选择。我放了debugger
。您可以通过使用 F12 打开控制台来重现错误。 如果我的方法有误,我可以完全改变我的方法。
当您使用 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>
更新
好吧,从整个问题的角度来看,也许是时候创建一个组件来控制国家和州了。它更复杂一些,因为我们必须使用 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>
我有一个 angular 应用程序。我在下面的示例中使用了级联组合框(国家/地区)。但是,get states()
方法在state.component.ts
运行宁了很多时间。这可能是什么原因?我只想 运行 只更改国家/地区选择。我放了debugger
。您可以通过使用 F12 打开控制台来重现错误。 如果我的方法有误,我可以完全改变我的方法。
当您使用 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>
更新 好吧,从整个问题的角度来看,也许是时候创建一个组件来控制国家和州了。它更复杂一些,因为我们必须使用 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>