我正在使用 Angular5 和 primeng 库。特别是,我对 p-dropdown 有问题。我有一个大实体 - 寄售 - 有很多字段,我打开包含此保存对象的页面。并且几个 p-dropdown 元素(这里是合同组件)不显示所选值。但是,我确信没有对象的空字段。看起来,就像与 p-dropdown options 属性链接的数组一样,当与 p-dropdown ngModel 相关的 @Input() 字段不是空时,它仍然是空的。我如何在 ngModel 字段启动之前填写选项数组?或者可能还有另一个问题?我的代码如下:
HTML模板:
<div class="form-group ui-float-label">
<p-dropdown [options]="selectItems" [(ngModel)]="contract" [filter]="true" (onChange)="onContractSelect()"
[style]="{'width':'100%'}" id="contract" placeholder="Select a contract" [required]="required" ></p-dropdown>
<label for="contract" [hidden]="contract == null">Contract</label>
</div>
组件代码:
export class SelectContractComponent implements OnChanges{
public contracts : Contract[] = [];
@Input() contract: Contract;
@Output() contractChange = new EventEmitter();
@Input() contractor: Contractor;
selectItems: SelectItem[]= [];
@Input() disabled: boolean;
@Input() required: boolean;
constructor(
private contractService: ContractService) {
}
ngOnChanges(changes: SimpleChanges): void {
this.getAllContracts();
const contractor: SimpleChange = changes.contractor;
this.selectItems = [];
if (contractor != null && contractor.currentValue != null){
this.getContractsByContractor();
}
}
private fillSelectItems(contract: Contract){
this.selectItems.push({label: contract.name, value: contract});
}
getContractsByContractor():void {
this.contractService.getContractsByContractor(this.contractor.id)
.subscribe(contracts => {
this.contracts = contracts;
this.contracts.forEach(c => this.fillSelectItems(c));
});
}
getAllContracts():void{
this.contractService.getContracts()
.subscribe(contracts => {
this.contracts = contracts;
this.contracts.forEach(c => this.fillSelectItems(c));
});
}
public onContractSelect(){
this.contractChange.emit(this.contract);
}
}
寄售模板片段:
<app-select-contract [(contract)]="consignment.costPayerContract" [contractor]="consignment.costPayer"
*ngIf="consignment.costPayer"></app-select-contract>
我找到了解决方案。我必须为 ngModel 创建其他一个字段,并在填写 selectItems 后将该字段分配给合同的字段。
HTML模板:
<div class="form-group ui-float-label">
<p-dropdown [options]="selectItems" **[(ngModel)]="selectedItem"** [filter]="true" (onChange)="onContractSelect()"
[style]="{'width':'100%'}" id="contract" placeholder="Select a contract" [required]="required" ></p-dropdown>
<label for="contract" [hidden]="contract == null">Contract</label>
</div>
组件类:
export class SelectContractComponent implements OnChanges{
public contracts : Contract[] = [];
@Input() contract: Contract;
@Output() contractChange = new EventEmitter();
@Input() contractor: Contractor;
selectItems: SelectItem[] = [];
**selectedItem: Contract;**
@Input() disabled: boolean;
@Input() required: boolean;
constructor(
private contractService: ContractService) {
}
ngOnChanges(changes: SimpleChanges): void {
console.log('select contract on changes');
const contractor: SimpleChange = changes.contractor;
if (contractor != null && contractor.currentValue != null){
this.getContractsByContractor();
} else {
this.getAllContracts();
}
console.log('select contract on changes end');
}
getContractsByContractor():void {
this.contractService.getContractsByContractor(this.contractor.id)
.subscribe(contracts => {
this.contracts = contracts;
this.fillSelectItems();
console.log('before assign selected item');
**this.selectedItem = this.contract;**
});
}
getAllContracts():void{
this.contractService.getContracts()
.subscribe(contracts => {
this.contracts = contracts;
this.fillSelectItems();
console.log('before assign selected item');
**this.selectedItem = this.contract;**
});
}
public onContractSelect(){
this.contractChange.emit(this.selectedItem);
}
fillSelectItems():void{
console.log('filling select items');
this.selectItems = [];
this.contracts.forEach(c => this.selectItems.push({label: c.name, value: c}));
console.log('filling select items end');
}
}
我在 primeng 的代码中发现了一个竞争条件,如果您设置选项,然后在之后立即设置 selectedOption(在同一线程/函数中),它将无法使用 selectedOption 更新显示。 一个快速的解决方法是在设置选项后添加一个可观察的对象(在设置 selectedOption 之前给予 primeng 时间来更新其数据)
public randomSetFunction(options: any, selectedOption: any) {
this.options = options;
of(this.options).subscribe(opts => { this.selectedOption = selectedOption });
}
这个问题可能会在Primeng的更高版本中得到修复(我用7.1.3测试过)