diff --git a/examples/components/CRUD/List.jsx b/examples/components/CRUD/List.jsx index 15d65c389..18aef7409 100644 --- a/examples/components/CRUD/List.jsx +++ b/examples/components/CRUD/List.jsx @@ -3,32 +3,18 @@ export default { remark: 'bla bla bla', body: { type: 'crud', - api: '/api/sample', + name: 'thelist', + api: { + method: 'get', + url: '/api/sample', + sendOn: '${mode}' + }, mode: 'list', draggable: true, saveOrderApi: { url: '/api/sample/saveOrder' }, orderField: 'weight', - filter: { - title: '条件搜索', - submitText: '', - body: [ - { - type: 'input-text', - name: 'keywords', - placeholder: '通过关键字搜索', - addOn: { - label: '搜索', - type: 'submit' - } - }, - { - type: 'plain', - text: '这只是个示例, 目前搜索对查询结果无效.' - } - ] - }, affixHeader: true, bulkActions: [ { @@ -63,6 +49,44 @@ export default { ], quickSaveApi: '/api/sample/bulkUpdate', quickSaveItemApi: '/api/sample/$id', + headerToolbar: [ + { + type: 'form', + mode: 'inline', + wrapWithPanel: false, + submitOnChange: true, + submitOnInit: true, + target: 'thelist', + body: [ + { + type: 'select', + name: 'mode', + className: 'mb-0', + selectFirst: true, + options: [ + { + label: '模式 1', + value: 'mode1' + }, + { + label: '模式 2', + value: 'mode2' + } + ] + }, + { + type: 'input-text', + name: 'keywords', + placeholder: '通过关键字搜索', + className: 'mb-0', + addOn: { + label: '搜索', + type: 'submit' + } + } + ] + } + ], listItem: { actions: [ { diff --git a/packages/amis-core/src/SchemaRenderer.tsx b/packages/amis-core/src/SchemaRenderer.tsx index a1871156f..50913dff4 100644 --- a/packages/amis-core/src/SchemaRenderer.tsx +++ b/packages/amis-core/src/SchemaRenderer.tsx @@ -64,7 +64,8 @@ export const RENDERER_TRANSMISSION_OMIT_PROPS = [ 'label', 'renderLabel', 'trackExpression', - 'editorSetting' + 'editorSetting', + 'updatePristineAfterStoreDataReInit' ]; const componentCache: SimpleMap = new SimpleMap(); diff --git a/packages/amis-core/src/WithStore.tsx b/packages/amis-core/src/WithStore.tsx index bb57467ca..6c9a0d4b9 100644 --- a/packages/amis-core/src/WithStore.tsx +++ b/packages/amis-core/src/WithStore.tsx @@ -207,7 +207,8 @@ export function HocStoreFactory(renderer: { ...(store.hasRemoteData ? store.data : null), // todo 只保留 remote 数据 ...this.formatData(props.defaultData), ...this.formatData(props.data) - }) + }), + props.updatePristineAfterStoreDataReInit === false ); } } else if ( @@ -234,7 +235,8 @@ export function HocStoreFactory(renderer: { store, props.syncSuperStore === true ) - ) + ), + props.updatePristineAfterStoreDataReInit === false ); } else if (props.data && (props.data as any).__super) { store.initData( @@ -245,6 +247,10 @@ export function HocStoreFactory(renderer: { ...store.data, ...props.data } + : // combo 不需要同步,如果要同步,在 Combo.tsx 里面已经实现了相关逻辑 + // 目前主要的问题是,如果 combo 中表单项名字和 combo 本身的名字一样,会导致里面的值会被覆盖成数组 + props.store?.storeType === 'ComboStore' + ? undefined : syncDataFromSuper( props.data, (props.data as any).__super, @@ -252,10 +258,14 @@ export function HocStoreFactory(renderer: { store, false ) - ) + ), + props.updatePristineAfterStoreDataReInit === false ); } else { - store.initData(createObject(props.scope, props.data)); + store.initData( + createObject(props.scope, props.data), + props.updatePristineAfterStoreDataReInit === false + ); } } else if ( !props.trackExpression && @@ -278,8 +288,9 @@ export function HocStoreFactory(renderer: { ...store.data }), - store.storeType === 'FormStore' && - prevProps.store?.storeType === 'CRUDStore' + props.updatePristineAfterStoreDataReInit === false || + (store.storeType === 'FormStore' && + prevProps.store?.storeType === 'CRUDStore') ); } // nextProps.data.__super !== props.data.__super) && @@ -295,7 +306,8 @@ export function HocStoreFactory(renderer: { createObject(props.scope, { // ...nextProps.data, ...store.data - }) + }), + props.updatePristineAfterStoreDataReInit === false ); } } diff --git a/packages/amis-core/src/store/crud.ts b/packages/amis-core/src/store/crud.ts index cb63256f4..3a2a1155f 100644 --- a/packages/amis-core/src/store/crud.ts +++ b/packages/amis-core/src/store/crud.ts @@ -61,12 +61,11 @@ export const CRUDStore = ServiceStore.named('CRUDStore') // 因为会把数据呈现在地址栏上。 return createObject( createObject(self.data, { - ...self.query, items: self.items.concat(), selectedItems: self.selectedItems.concat(), unSelectedItems: self.unSelectedItems.concat() }), - {} + {...self.query} ); }, diff --git a/packages/amis/__tests__/renderers/Form/combo.test.tsx b/packages/amis/__tests__/renderers/Form/combo.test.tsx index 5537d67c2..c40724bcd 100644 --- a/packages/amis/__tests__/renderers/Form/combo.test.tsx +++ b/packages/amis/__tests__/renderers/Form/combo.test.tsx @@ -969,3 +969,35 @@ test('Renderer:select autofill in combo', async () => { combo: [{type: '1', a: 'a'}] }); }); + +// 10. combo 内部表单项与 combo 同名时,原来会出现内部表单项的值变成数组的情况 +test('Renderer:combo 内部表单项与 combo 同名', async () => { + const {container, submitBtn, findByText, onSubmit, baseElement} = await setup( + [ + { + type: 'combo', + name: 'a', + label: 'combo', + className: 'removableFalse', + removable: false, + multiple: true, + items: [ + { + name: 'a', + type: 'input-text', + label: 'A' + } + ], + value: [{}] + } + ] + ); + + const input = container.querySelector('input[name="a"]') as HTMLInputElement; + fireEvent.change(input, {target: {value: '1'}}); + await wait(400); + + fireEvent.change(input, {target: {value: '123'}}); + await wait(400); + expect(input.value).toBe('123'); +}); diff --git a/packages/amis/src/renderers/Form/Combo.tsx b/packages/amis/src/renderers/Form/Combo.tsx index 3a180bd78..0f3437f2e 100644 --- a/packages/amis/src/renderers/Form/Combo.tsx +++ b/packages/amis/src/renderers/Form/Combo.tsx @@ -1719,7 +1719,8 @@ export default class ComboControl extends React.Component { ref: this.makeFormRef(0), onInit: this.handleSingleFormInit, canAccessSuperData, - formStore: undefined + formStore: undefined, + updatePristineAfterStoreDataReInit: false } ); } else if (multiple && index !== undefined && index >= 0) { @@ -1750,7 +1751,8 @@ export default class ComboControl extends React.Component { value: undefined, formItemValue: undefined, formStore: undefined, - ...(tabsMode ? {} : {lazyLoad}) + ...(tabsMode ? {} : {lazyLoad}), + updatePristineAfterStoreDataReInit: false } ); } diff --git a/vite.config.ts b/vite.config.ts index ea9fdb7f3..17c70cc06 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -62,7 +62,8 @@ export default defineConfig({ }), monacoEditorPlugin({}), replace({ - __editor_i18n: !!I18N + __editor_i18n: !!I18N, + preventAssignment: true }) ].filter(n => n), optimizeDeps: {