/** * Lookup cascade (bağımlı açılır liste) davranışı. * Grid ve Tree aynı kuralları paylaşır. */ import type { GridDto } from '@/proxy/form/models' export type CascadeInfo = { parentFields: string[] childFields?: string[] } export type CascadeMaps = { /** fieldName -> cascade bilgisi */ cascadeFieldsMap: Map /** parentField -> etkilediği child alan adları */ parentToChildrenMap: Map> } const splitFields = (value?: string | null) => (value ?? '') .split(',') .map((field) => field.trim()) .filter(Boolean) export const createCascadeMaps = (gridDto?: GridDto): CascadeMaps => { const cascadeFieldsMap = new Map() const parentToChildrenMap = new Map>() gridDto?.columnFormats.forEach((col) => { if (!col.fieldName || !col.lookupDto?.cascadeParentFields) return const parentFields = splitFields(col.lookupDto.cascadeParentFields) const childFields = col.lookupDto.cascadeEmptyFields ? splitFields(col.lookupDto.cascadeEmptyFields) : undefined cascadeFieldsMap.set(col.fieldName, { parentFields, childFields }) parentFields.forEach((parentField) => { const children = parentToChildrenMap.get(parentField) ?? new Set() children.add(col.fieldName!) parentToChildrenMap.set(parentField, children) }) }) return { cascadeFieldsMap, parentToChildrenMap } } type AttachCascadeParams = { editor: any gridDto: GridDto cascadeInfo: CascadeInfo maps: CascadeMaps } /** * `onEditorPreparing` içinde cascade davranışını editöre bağlar: * - parent değiştiğinde child alanları temizler, * - etkilenen child editörlerin `disabled` durumunu günceller, * - form ilk açıldığında parent'ı boş olan alanı devre dışı bırakır. */ export const attachCascadeBehavior = ({ editor, gridDto, cascadeInfo, maps, }: AttachCascadeParams) => { const { cascadeFieldsMap, parentToChildrenMap } = maps const affectedChildren = parentToChildrenMap.get(editor.dataField) const previousHandler = editor.editorOptions.onValueChanged editor.editorOptions.onValueChanged = (e: any) => { previousHandler?.(e) const grid = editor.component const rowKey = grid.option('editing.editRowKey') const rowIndex = grid.getRowIndexByKey(rowKey) // Parent değiştiğinde bağımlı alanları temizle. if (cascadeInfo.childFields && rowIndex >= 0) { cascadeInfo.childFields.forEach((childField) => grid.cellValue(rowIndex, childField, null)) } if (!affectedChildren?.size) return const formInstance = grid.option('editing.form') as any if (!formInstance?.getEditor) return const rowData = grid.getVisibleRows().find((row: any) => row.key === rowKey)?.data if (!rowData) return affectedChildren.forEach((childFieldName) => { const childInfo = cascadeFieldsMap.get(childFieldName) if (!childInfo) return try { const childColumn = gridDto.columnFormats.find( (column) => column.fieldName === childFieldName, ) const childEditorOptions = childColumn?.editorOptions ? JSON.parse(childColumn.editorOptions) : {} const childEditor = formInstance.getEditor(childFieldName) childEditor?.option( 'disabled', childEditorOptions?.disabled === true || childInfo.parentFields.some((parentField) => !rowData[parentField]), ) } catch (err) { console.error(`Cascade child editor güncellenemedi: "${childFieldName}"`, err) } }) } // İlk açılışta parent'ı dolu değilse editörü kilitle. const grid = editor.component const rowKey = grid.option('editing.editRowKey') const rowData = grid.getVisibleRows().find((row: any) => row.key === rowKey)?.data if (rowData && cascadeInfo.parentFields.some((parentField) => !rowData[parentField])) { editor.editorOptions.disabled = true } }