Skip to content

Commit

Permalink
chore: 调整表单项初始化过程 解决表单项非初始渲染时 initAutoFill 配置无效的问题 Close: baidu#9733, b…
Browse files Browse the repository at this point in the history
  • Loading branch information
2betop committed Mar 7, 2024
1 parent bf0e4d0 commit c4aac4b
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 82 deletions.
51 changes: 25 additions & 26 deletions packages/amis-core/src/renderers/Item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -635,26 +635,6 @@ export class FormItemWrap extends React.Component<FormItemProps> {
)
);

this.toDispose.push(
reaction(
() => JSON.stringify(model.tmpValue),
() =>
this.mounted &&
this.initedApiFilled &&
this.syncApiAutoFill(model.tmpValue)
)
);

this.toDispose.push(
reaction(
() => JSON.stringify(model.getSelectedOptions(model.tmpValue)),
() =>
this.mounted &&
this.initedOptionFilled &&
this.syncOptionAutoFill(model.getSelectedOptions(model.tmpValue))
)
);

let onInit = () => {
this.initedOptionFilled = true;
initAutoFill !== false &&
Expand All @@ -669,13 +649,32 @@ export class FormItemWrap extends React.Component<FormItemProps> {
false,
initAutoFill === 'fillIfNotSet'
);

this.toDispose.push(
reaction(
() => JSON.stringify(model.tmpValue),
() =>
this.mounted &&
this.initedApiFilled &&
this.syncApiAutoFill(model.tmpValue)
)
);

this.toDispose.push(
reaction(
() => JSON.stringify(model.getSelectedOptions(model.tmpValue)),
() =>
this.mounted &&
this.initedOptionFilled &&
this.syncOptionAutoFill(model.getSelectedOptions(model.tmpValue))
)
);
};
if (formInited || !addHook) {
onInit();
} else if (addHook) {
// 放在初始化的最后面
this.toDispose.push(addHook(onInit, 'init', 'post'));
}
this.toDispose.push(
formInited || !addHook
? model.addInitHook(onInit, 999)
: addHook(onInit, 'init', 'post')
);
}

componentDidMount() {
Expand Down
54 changes: 29 additions & 25 deletions packages/amis-core/src/renderers/Options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -329,34 +329,36 @@ export function registerOptionsControl(config: OptionsConfig) {
defaultCheckAll
} = props;

if (formItem) {
formItem.setOptions(
normalizeOptions(options, undefined, valueField),
this.changeOptionValue,
data
);
if (!formItem) {
return;
}

this.toDispose.push(
reaction(
() => JSON.stringify([formItem.loading, formItem.filteredOptions]),
() => this.mounted && this.forceUpdate()
)
);
formItem.setOptions(
normalizeOptions(options, undefined, valueField),
this.changeOptionValue,
data
);

// 默认全选。这里会和默认值\回填值逻辑冲突,所以如果有配置source则不执行默认全选
if (
multiple &&
defaultCheckAll &&
formItem.filteredOptions?.length &&
!source
) {
this.defaultCheckAll();
}
this.toDispose.push(
reaction(
() => JSON.stringify([formItem.loading, formItem.filteredOptions]),
() => this.mounted && this.forceUpdate()
)
);

// 默认全选。这里会和默认值\回填值逻辑冲突,所以如果有配置source则不执行默认全选
if (
multiple &&
defaultCheckAll &&
formItem.filteredOptions?.length &&
!source
) {
this.defaultCheckAll();
}

let loadOptions: boolean = initFetch !== false;

if (formItem && joinValues === false && defaultValue) {
if (joinValues === false && defaultValue) {
const selectedOptions = extractValue
? formItem
.getSelectedOptions(value)
Expand All @@ -372,9 +374,11 @@ export function registerOptionsControl(config: OptionsConfig) {

loadOptions &&
config.autoLoadOptionsFromSource !== false &&
(formInited || !addHook
? this.reload()
: this.toDispose.push(addHook(this.initOptions, 'init')));
this.toDispose.push(
formInited || !addHook
? formItem.addInitHook(this.reload)
: addHook(this.initOptions, 'init')
);
}

componentDidMount() {
Expand Down
2 changes: 2 additions & 0 deletions packages/amis-core/src/renderers/wrapControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ export function wrapControl<
};
addHook?.(this.hook2);
}

formItem?.init();
}

componentDidUpdate(prevProps: OuterProps) {
Expand Down
38 changes: 36 additions & 2 deletions packages/amis-core/src/store/formItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import {
eachTree,
mapTree,
setVariable,
cloneObject
cloneObject,
promisify
} from '../utils/helper';
import {flattenTree} from '../utils/helper';
import find from 'lodash/find';
Expand Down Expand Up @@ -91,6 +92,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
itemId: '', // 因为 name 可能会重名,所以加个 id 进来,如果有需要用来定位具体某一个
unsetValueOnInvisible: false,
itemsRef: types.optional(types.array(types.string), []),
inited: false,
validated: false,
validating: false,
multiple: false,
Expand Down Expand Up @@ -318,6 +320,8 @@ export const FormItemStore = StoreNode.named('FormItemStore')
const dialogCallbacks = new SimpleMap<(result?: any) => void>();
let loadAutoUpdateCancel: Function | null = null;

const initHooks: Array<(store: any) => any> = [];

function config({
name,
extraName,
Expand Down Expand Up @@ -1495,6 +1499,19 @@ export const FormItemStore = StoreNode.named('FormItemStore')
self.isControlled = !!value;
}

const init: () => Promise<void> = flow(function* init() {
const hooks = initHooks.sort(
(a: any, b: any) => (a.__weight || 0) - (b.__weight || 0)
);
try {
for (let hook of hooks) {
yield hook(self);
}
} finally {
self.inited = true;
}
});

return {
focus,
blur,
Expand Down Expand Up @@ -1523,7 +1540,24 @@ export const FormItemStore = StoreNode.named('FormItemStore')
addSubFormItem,
removeSubFormItem,
loadAutoUpdateData,
setIsControlled
setIsControlled,

init,

addInitHook(fn: (store: any) => any, weight = 0) {
fn = promisify(fn);
initHooks.push(fn);
(fn as any).__weight = weight;
return () => {
const idx = initHooks.indexOf(fn);
~idx && initHooks.splice(idx, 1);
};
},

beforeDestroy: () => {
// 销毁
initHooks.splice(0, initHooks.length);
}
};
});

Expand Down
4 changes: 4 additions & 0 deletions packages/amis/__tests__/renderers/Form/formitem.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -409,3 +409,7 @@ test('Renderer:Formitem initial value in table', async () => {
);
expect(container.innerHTML).toContain('123');
});

// TODO 补充测试用例
// https://github.com/baidu/amis/issues/9742
// https://github.com/baidu/amis/issues/9733
26 changes: 18 additions & 8 deletions packages/amis/src/renderers/Form/InputFile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
executor: () => void;
}> = [];
initedFilled = false;
toDispose: Array<() => void> = [];

static valueToFile(
value: string | FileValue,
Expand Down Expand Up @@ -446,17 +447,19 @@ export default class FileControl extends React.Component<FileProps, FileState> {
}

componentDidMount() {
const {formInited, addHook} = this.props;
const {formInited, addHook, formItem} = this.props;

if (formInited || !addHook) {
const onInited = () => {
this.initedFilled = true;
this.props.initAutoFill && this.syncAutoFill();
} else if (addHook) {
addHook(() => {
this.initedFilled = true;
this.props.initAutoFill && this.syncAutoFill();
}, 'init');
}
};

formItem &&
this.toDispose.push(
formInited || !addHook
? formItem.addInitHook(onInited)
: addHook(onInited, 'init')
);
}

componentDidUpdate(prevProps: FileProps) {
Expand Down Expand Up @@ -514,6 +517,13 @@ export default class FileControl extends React.Component<FileProps, FileState> {
}
}

componentWillUnmount(): void {
this.toDispose.forEach(fn => fn());
this.toDispose = [];
this.fileUploadCancelExecutors.forEach(item => item.executor());
this.fileUploadCancelExecutors = [];
}

handleDrop(files: Array<FileX>) {
if (!files.length) {
return;
Expand Down
23 changes: 15 additions & 8 deletions packages/amis/src/renderers/Form/InputImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ export default class ImageControl extends React.Component<
// 文件重新上传的位置标记,用以定位替换
reuploadIndex: undefined | number = undefined;

toDispose: Array<() => void> = [];

constructor(props: ImageProps) {
super(props);
const value: string | Array<string | FileValue> | FileValue = props.value;
Expand Down Expand Up @@ -514,17 +516,19 @@ export default class ImageControl extends React.Component<
}

componentDidMount() {
const {formInited, addHook} = this.props;
const {formInited, addHook, formItem} = this.props;

if (formInited || !addHook) {
const onInited = () => {
this.initedFilled = true;
this.props.initAutoFill && this.syncAutoFill();
} else if (addHook) {
addHook(() => {
this.initedFilled = true;
this.props.initAutoFill && this.syncAutoFill();
}, 'init');
}
};

formItem &&
this.toDispose.push(
formInited || !addHook
? formItem.addInitHook(onInited)
: addHook(onInited, 'init')
);

if (this.props.initCrop && this.files.length) {
this.editImage(0);
Expand Down Expand Up @@ -598,6 +602,9 @@ export default class ImageControl extends React.Component<
componentWillUnmount() {
this.unmounted = true;
this.fileKeys = new WeakMap();

this.toDispose.forEach(fn => fn());
this.toDispose = [];
}

getFileKey(file: FileValue | FileX) {
Expand Down
14 changes: 10 additions & 4 deletions packages/amis/src/renderers/Form/MatrixCheckboxes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export default class MatrixCheckbox extends React.Component<

state: MatrixState;
mounted: boolean = false;
toDispose: Array<() => void> = [];

constructor(props: MatrixProps) {
super(props);
Expand All @@ -128,9 +129,14 @@ export default class MatrixCheckbox extends React.Component<
}

componentDidMount() {
const {formInited, addHook} = this.props;
const {formInited, addHook, formItem} = this.props;

formInited || !addHook ? this.reload() : addHook(this.initOptions, 'init');
formItem &&
this.toDispose.push(
formInited || !addHook
? formItem.addInitHook(this.initOptions)
: addHook(this.initOptions, 'init')
);
}

componentDidUpdate(prevProps: MatrixProps) {
Expand Down Expand Up @@ -164,8 +170,8 @@ export default class MatrixCheckbox extends React.Component<

componentWillUnmount() {
this.mounted = false;
const {removeHook} = this.props;
removeHook?.(this.initOptions, 'init');
this.toDispose.forEach(fn => fn());
this.toDispose = [];
}

doAction(action: ActionObject, data: object, throwErrors: boolean) {
Expand Down

0 comments on commit c4aac4b

Please sign in to comment.