我正在使用 Syncfusion 的 Angular ComboBox 组件,并设置了一个场景来演示基于选择另一个 ComboBox 刷新 ComboBox 数据源的问题。详情如下:
我创建了两个组合框: 项目组合框:允许选择项目。 单位组合框:应刷新以根据项目组合框中所选项目显示相关单位
当用户从 Item ComboBox 中选择一个项目时,我调用 reloadCombo() 方法,通过根据所选项目键获取相应的单位来更新 Unit ComboBox 的数据源。然而,这次刷新似乎没有按预期工作——Unit ComboBox 的数据源没有更新。
其他详细信息
简单模拟:对于这个示例,我创建了一个简单的服务来模拟基于项目键的服务器数据检索。在 实际项目中,我调用API来根据所选的单位数据获取 项目键
项目复杂性:此处提供的示例经过简化。我的真实项目涉及比较复杂的多层次亲子 关系,所以我需要严格遵循这个结构 与整体应用程序的兼容性。不幸的是,我不能 进一步简化ComboBox数据更新逻辑。
尝试过的方法:我尝试过在Unit ComboBox上调用dataBind()和refresh()来强制更新,但都没有解决这个问题 问题。
我附上了此设置的工作示例以供参考。
是否有一种特定的方法可以根据此结构中另一个组合框的选定值动态刷新一个组合框?任何指导将不胜感激。
谢谢你。
我没有使用函数调用一次又一次地初始化可观察流
this.comdoDataSource
,而是使用BehaviorSubject
将其更改为可观察流。
refreshSub: BehaviorSubject<string> = new BehaviorSubject<string>('');
...
...
reload() {
this.refreshSub.next(new Date().getTime().toString());
}
fetchData(): Observable<any> {
this.comdoDataSource = this.refreshSub
.pipe(
switchMap(() => {
return this.itemUnitService.getUnitsForItem(this.comboRequest);
})
)
.pipe(
tap((res: any) => {
this.unitArray = res;
// setTimeout(() => {
this.combo.refresh();
// });
})
);
return this.comdoDataSource;
}
应用程序组件将简单地调用
reload
方法,我们在其中使用 refreshSub
为 BehaviorSubject
(this.refreshSub.next(new Date().getTime().toString())
) 发出新值。
这会触发从
BehaviorSubject
开始并转到 switchMap
的流,检索数据,最后转到 tap
方法,我在其中调用 this.combo.refresh();
重新加载新数据。
如果您遇到任何问题,只需将
this.combo.refresh()
包裹在 setTimeout
中即可正常工作。
import {
Component,
OnInit,
Input,
OnDestroy,
ChangeDetectorRef,
Output,
EventEmitter,
ViewChild,
} from '@angular/core';
import {
BehaviorSubject,
Observable,
Subject,
catchError,
concat,
debounceTime,
distinctUntilChanged,
filter,
map,
of,
switchMap,
tap,
} from 'rxjs';
import {
ChangeEventArgs,
ComboBoxComponent,
FilteringEventArgs,
PopupEventArgs,
} from '@syncfusion/ej2-angular-dropdowns';
import { EmitType } from '@syncfusion/ej2-base';
import { UnitResponse } from '../../entity/unit-response';
import { ItemService } from '../../service/item.setvice';
import { ComboRequest } from '../../entity/item-response';
@Component({
selector: 'app-unit-combo-box',
templateUrl: './unit-combo-box.component.html',
styleUrl: './unit-combo-box.component.css',
})
export class UnitComboBoxComponent implements OnDestroy {
@ViewChild(ComboBoxComponent) combo: ComboBoxComponent;
selectedDataItem!: UnitResponse;
itemsLoading = false;
searchInput = new Subject<string>();
comdoDataSource!: Observable<UnitResponse[]>;
public fields: Object = { text: 'unitName' };
isEditable: boolean = true;
cssClass: string | null = '';
unitArray: Array<any>;
comboRequest: ComboRequest = new ComboRequest();
refreshSub: BehaviorSubject<string> = new BehaviorSubject<string>('');
constructor(private itemUnitService: ItemService) {}
ngAfterViewInit() {
this.initializeCombo();
}
initializeCombo() {
this.readCombo();
}
reload() {
this.refreshSub.next(new Date().getTime().toString());
}
fetchData(): Observable<any> {
this.comdoDataSource = this.refreshSub
.pipe(
switchMap(() => {
return this.itemUnitService.getUnitsForItem(this.comboRequest);
})
)
.pipe(
tap((res: any) => {
this.unitArray = res;
// setTimeout(() => {
this.combo.refresh();
// });
})
);
return this.comdoDataSource;
}
onBeforeComboRead() {}
readCombo() {
this.onBeforeComboRead();
this.fetchData();
}
onAfterComboRead() {}
reloadCombo(itemky: number) {
console.log('unit combo reload', itemky);
// i should reload and update the datasource based on given item key
this.comboRequest.itmKy = itemky;
this.reload();
}
onSelectionChange(ev: ChangeEventArgs) {
this.selectedDataItem = ev.value as UnitResponse;
}
onFiltering: EmitType<FilteringEventArgs> = (e: FilteringEventArgs) => {};
onClearvalue(e: PopupEventArgs) {
// this.comdoDataSource = this.fetchData();
}
ngOnDestroy(): void {}
}