如何将Observable @Input传入Angular组件商店?首次加载失败排查
问题分析与解决方案
问题根源
首次打开对话框不加载数据、第二次才加载的核心原因是:@Input setter中调用的this.store.update并未正确更新ComponentStore的状态。
你的SalesHistoryStore仅定义了setWarehousesToShow这个updater方法,却没有专门用于更新salesHistory状态的updater。直接调用this.store.update(假设OodleComponentStore未提供默认update方法)不会触发状态变更,导致salesHistory$始终发出初始空数组。第二次打开时,父组件的salesHistory$已有缓存值,async管道会立即传递数据,此时setter可能在组件初始化前触发,才让表格拿到有效数据。
修复步骤
1. 在Store中添加更新salesHistory的updater方法
修改SalesHistoryStore,新增专门的updater处理salesHistory状态更新:
@Injectable() export class SalesHistoryStore extends OodleComponentStore<SalesHistoryState> { constructor(private whsService: WarehouseService) { super({ salesHistory: [], warehousesToShow: [], isLoaded: false // 显式标记初始未加载状态 }); } // 新增:更新salesHistory的updater方法 updateSalesHistory = this.updater((state, salesHistory: SalesHistoryLine[]) => ({ ...state, salesHistory, isLoaded: true // 标记数据已加载 })); // 原有代码保持不变 salesHistoryWithWhColors$: Observable<SalesHistoryLine[]> = this.select(state => state.salesHistory.filter(value => !!value).map(csh => ({ ...csh, color: this.whsService.whsColorLookup[csh.warehouseId] })) ); warehousesToShow$: Observable<number[]> = this.select(state => state.warehousesToShow); salesHistory$: Observable<SalesHistoryLine[]> = this.select( this.select(state => state.isLoaded), this.salesHistoryWithWhColors$, this.warehousesToShow$, (isLoaded, salesHistoryLines, warehousesToShow) => { if (!isLoaded) return []; return salesHistoryLines.filter(shl => warehousesToShow ? warehousesToShow.includes(shl.warehouseId) : true ); } ); setWarehousesToShow = this.updater((state, warehousesToShow: number[]) => ({ ...state, warehousesToShow })); }
2. 修改@Input setter,调用正确的updater
将子组件的@Input setter改为调用新增的updateSalesHistory方法:
@Input() set salesHistory(val: SalesHistoryLine[]) { // 过滤空值,避免覆盖有效状态 if (val?.length) { this.store.updateSalesHistory(val); } }
验证逻辑
修复后,当父组件通过async管道传递数据时,setter会触发Store状态更新,salesHistory$会立即发出过滤后的有效数据,TableBuilder能实时接收到数据,首次打开对话框即可正常显示销售记录。
内容的提问来源于stack exchange,提问作者Sora Teichman
相关产品推荐
相关产品推荐

