我有一个小应用here。
它的作用:它有3个下拉列表,表示地址选择 - 区,市和结算。它们相互依赖,因此在一个下拉列表中选择的内容决定了下一个下拉列表中的项目。有一个根组件将3个输入数字值传递给子组件(我还添加了一些延迟来模拟http调用)。
我的目标:为了能够立即更新根组件中的值,只要子组件发生变化(在AngularJS 1中,我们对子指令有=
选项范围)。这就是为什么我对属性使用双向绑定的原因,你可以看到我必须在发生变化时发出。我还希望将数据作为简单的数字属性传递,而不是将子组件绑定到具有3个属性的某个自定义类。
我遇到的问题:
1)每当有变化时我都必须通过EventEmitter<numner>
手动发出(因为我有3个简单类型的属性)。 我们没有在AngularJS 1中做到这一点,那么有更灵活的解决方案吗?
2)您看到的应用有效,因为我在enableProdMode
文件中添加了对main.ts
的调用。那是因为我需要违反NG4 +的单向流规则:当一个下拉列表中的值发生变化时会发生这种情况,然后我需要将相关值设置为null并更新OnChanges钩子中依赖下拉列表中的项目(例如,当我改变地区时,市政当局必须无效)。 是否有更好的方法来执行此操作,或者可以违反规则,知道自己在做什么?
答案 0 :(得分:1)
我的应用程序中有两个下拉列表,它们也相互依赖。我使用反应形式并订阅价值变化:
slots$: Observable<Array<SlotIdentity>>;
ngOnInit(): void {
this.buildRoleForm();
this.slots$ = this.formGroup.get('pageId')
.valueChanges
.map(pageId => _.sortBy(this.pages.find(({id}) => id === +pageId).slots, 'slotNumber'))
.do(() => this.formGroup.get('slotId').setValue(''));
}
private buildRoleForm() {
this.formGroup = this.formBuilder.group({
pageId: ['', Validators.required],
slotId: ['', Validators.required]
});
}
html在这里:
<form [formGroup]="formGroup" novalidate>
<div class="row">
<div class="col-sm-6">
<label for="pageNumber" col-sm-6>Page#</label>
<select id="pageNumber" class="form-control" formControlName="pageId">
<option *ngFor="let page of pages" value="{{page.id}}">
{{page.pageNumber}}
</option>
</select>
</div>
<div class="col-sm-6">
<label for="slotNumber">Slot#</label>
<select id="slotNumber" class="form-control" formControlName="slotId">
<option *ngFor="let slot of slots$ | async" value="{{slot.id}}">
{{slot.slotNumber}}
</option>
</select>
</div>
</div>
</form>
答案 1 :(得分:0)
首先,我不会保留三个单独的数字,而是为它创建一些包装(让我们暂时将其称为wrapper
- 请记住来自Rest的调用你应该收到一个对象与领域)
export class Wrapper {
districtId: number;
municipalityId: number;
settlementId: number;
constructor(dist, mun, sett){
this.districtId = dist;
this.municipalityId = mun;
this.settlementId = sett;
}
}
然后我们的app.html看起来像:
District id: {{ wrapper.districtId }}
Minicipality id: {{ wrapper.municipalityId }}
Settlement id: {{ wrapper.settlementId }}
<my-child [wrapper]="wrapper"></my-child>
请注意,字段的每次更改都会自动显示在wrapper.districtId
等
我们可以简化我们的子组件:
当我们输入wrapper
对象时,我们不能将我们的逻辑基于OnChanges()(因为它会在对wrapper
对象的引用发生变化时调用,在我们的例子中只会更新字段),但我们可以在select
上调用特定函数:
<div>
<label for="district">District</label>
<select id="district" (change)="setMunicipalities()" [(ngModel)]="wrapper.districtId">
<option [value]="district.id" *ngFor="let district of districts">{{ district.name }}</option>
</select>
</div>
和最后的逻辑。请注意,当我们调用setMunicipalities()时,我们不需要检查是否有任何更改,请注意我们没有额外检查更改的内容(如前所述)
constructor(private changeDetector: ChangeDetectorRef) {
this.districts = DISTRICTS;
}
ngOnInit() {
this.setMunicipalities();
this.setSettlements();
}
private setMunicipalities() {
this.municipalities = MUNICIPALITIES.filter(mun => mun.districtId == this.wrapper.districtId);
this.setSettlements();
this.changeDetector.detectChanges();
}
private setSettlements(){
this.settlements = SETTLEMENTS.filter(sett => sett.municipalityId == this.wrapper.municipalityId);
}
我分叉你的plunker(https://plnkr.co/edit/A7aGJcZhQAryvVPLTrOA?p=preview) - 我在plunker中注入ChangeDetectorRef时遇到了问题(所以并不是所有的下拉都会自动更新,但希望你能感觉它应该如何工作)