fix: 修复 inputFile 的initAutoFill false 功能 Close: #7087 (#7191)

* chore: tpl 初始用同步模版渲染后更新异步模版 Close: #7099

* fix: 修复 inputFile 的initAutoFill false 功能 Close: #7087
This commit is contained in:
liaoxuezhi 2023-06-16 17:49:02 +08:00 committed by GitHub
parent a97dfe234d
commit 132761fcf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 55 deletions

View File

@ -223,14 +223,18 @@ export function wrapControl<
if (propValue !== undefined && propValue !== null) {
// 同步 value: 优先使用 props 中的 value
model.changeTmpValue(propValue);
model.changeTmpValue(propValue, 'controlled');
} else {
// 备注: 此处的 value 是 schema 中的 value和props.defaultValue相同
const curTmpValue = isExpression(value)
const isExp = isExpression(value);
const curTmpValue = isExp
? FormulaExec['formula'](value, data) // 对组件默认值进行运算
: store?.getValueByName(model.name) ?? replaceExpression(value); // 优先使用公式表达式
// 同步 value
model.changeTmpValue(curTmpValue);
model.changeTmpValue(
curTmpValue,
isExp ? 'formulaChanged' : 'defaultValue'
);
}
if (
@ -354,7 +358,7 @@ export function wrapControl<
!isEqual(props.value, model.tmpValue)
) {
// 外部直接传入的 value 无需执行运算器
model.changeTmpValue(props.value);
model.changeTmpValue(props.value, 'controlled');
}
} else if (
model &&
@ -386,46 +390,39 @@ export function wrapControl<
!isEqual(curResult, model.tmpValue)
) {
// 识别上下文变动、自身数值变动、公式运算结果变动
model.changeTmpValue(curResult);
model.changeTmpValue(curResult, 'formulaChanged');
props.onChange?.(curResult, model.name, false);
} else if (nowFormulaChecked) {
const nowData = props.data[model.name];
// now 表达式,计算后的值永远相同
model.changeTmpValue(nowData);
model.changeTmpValue(nowData, 'formulaChanged');
props.onChange?.(nowData, model.name, false);
}
}
} else if (model) {
const valueByName = getVariable(props.data, model.name);
if (isEqual(props.defaultValue, prevProps.defaultValue)) {
// value 非公式表达式时name 值优先,若 defaultValue 主动变动时,则使用 defaultValue
if (
// 然后才是查看关联的 name 属性值是否变化
props.data !== prevProps.data &&
(!model.emitedValue ||
isEqual(model.emitedValue, model.tmpValue))
) {
model.changeEmitedValue(undefined);
const prevValueByName = getVariable(props.data, model.name);
if (
(!isEqual(valueByName, prevValueByName) ||
getVariable(props.data, model.name, false) !==
getVariable(prevProps.data, model.name, false)) &&
!isEqual(valueByName, model.tmpValue)
) {
model.changeTmpValue(valueByName);
}
}
} else if (
!isEqual(props.defaultValue, prevProps.defaultValue) &&
!isEqual(props.defaultValue, model.tmpValue)
// value 非公式表达式时name 值优先,若 defaultValue 主动变动时,则使用 defaultValue
if (
// 然后才是查看关联的 name 属性值是否变化
props.data !== prevProps.data &&
(!model.emitedValue ||
isEqual(model.emitedValue, model.tmpValue))
) {
// 组件默认值非公式
const curValue = replaceExpression(props.defaultValue);
model.changeTmpValue(curValue);
if (props.onChange) {
props.onChange(curValue, model.name, false);
model.changeEmitedValue(undefined);
const prevValueByName = getVariable(props.data, model.name);
if (
(!isEqual(valueByName, prevValueByName) ||
getVariable(props.data, model.name, false) !==
getVariable(prevProps.data, model.name, false)) &&
!isEqual(valueByName, model.tmpValue)
) {
model.changeTmpValue(
valueByName,
props.formInited && !prevProps.formInited
? 'formInited'
: 'dataChanged'
);
}
}
}
@ -589,7 +586,7 @@ export function wrapControl<
value = pipeOut(value, oldValue, data);
}
this.model.changeTmpValue(value);
this.model.changeTmpValue(value, 'input');
if (changeImmediately || conrolChangeImmediately || !formInited) {
this.emitChange(submitOnChange);
@ -762,6 +759,7 @@ export function wrapControl<
ref: this.controlRef,
data: data || store?.data,
value,
changeMotivation: model?.changeMotivation,
defaultValue: control.value,
formItemValue: value, // 为了兼容老版本的自定义组件
onChange: this.handleChange,

View File

@ -61,6 +61,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
isValueSchemaExp: types.optional(types.boolean, false),
tmpValue: types.frozen(),
emitedValue: types.frozen(),
changeMotivation: 'input',
rules: types.optional(types.frozen(), {}),
messages: types.optional(types.frozen(), {}),
errorData: types.optional(types.array(ErrorDetail), []),
@ -1232,8 +1233,20 @@ export const FormItemStore = StoreNode.named('FormItemStore')
}
}
function changeTmpValue(value: any) {
function changeTmpValue(
value: any,
changeReason?:
| 'formInited' // 表单初始化
| 'dataChanged' // 表单数据变化
| 'formulaChanged' // 公式运算结果变化
| 'controlled' // 受控
| 'input' // 用户交互改变
| 'defaultValue' // 默认值
) {
self.tmpValue = value;
if (changeReason) {
self.changeMotivation = changeReason;
}
}
function changeEmitedValue(value: any) {

View File

@ -208,7 +208,7 @@ export class ItemPlugin extends BasePlugin {
const context = event.context;
if (
/\$/.test(context.info.renderer.name!) &&
context.info.renderer.isFormItem &&
context.diff?.some(change => change.path?.join('.') === 'value')
) {
const change: any = find(

View File

@ -348,7 +348,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
file: any;
executor: () => void;
}> = [];
initAutoFill: boolean;
initedFilled = false;
static valueToFile(
value: string | FileValue,
@ -398,7 +398,6 @@ export default class FileControl extends React.Component<FileProps, FileState> {
const joinValues = props.joinValues;
const delimiter = props.delimiter as string;
let files: Array<FileValue> = [];
this.initAutoFill = !!props.initAutoFill;
if (value && value instanceof Blob) {
files = [value as any];
@ -438,11 +437,16 @@ export default class FileControl extends React.Component<FileProps, FileState> {
}
componentDidMount() {
if (this.initAutoFill) {
const {formInited, addHook} = this.props;
formInited || !addHook
? this.syncAutoFill()
: addHook(this.syncAutoFill, 'init');
const {formInited, addHook} = this.props;
if (formInited || !addHook) {
this.initedFilled = true;
this.props.initAutoFill && this.syncAutoFill();
} else if (addHook) {
addHook(() => {
this.initedFilled = true;
this.props.initAutoFill && this.syncAutoFill();
}, 'init');
}
}
@ -494,7 +498,9 @@ export default class FileControl extends React.Component<FileProps, FileState> {
{
files: files
},
props.formInited !== false ? this.syncAutoFill : undefined
props.changeMotivation !== 'formInited' && this.initedFilled
? this.syncAutoFill
: undefined
);
}
}
@ -1486,7 +1492,8 @@ export default class FileControl extends React.Component<FileProps, FileState> {
{files.map((file, index) => {
const filename =
file[nameField as keyof typeof file] ||
(file as FileValue).filename;
(file as FileValue).filename ||
file.name;
return (
<li key={file.id}>

View File

@ -373,7 +373,8 @@ export default class ImageControl extends React.Component<
delimiter: ',',
autoUpload: true,
multiple: false,
dropCrop: true
dropCrop: true,
initAutoFill: true
};
static valueToFile(
@ -428,7 +429,7 @@ export default class ImageControl extends React.Component<
resolve?: (value?: any) => void;
emitValue: any;
unmounted = false;
initAutoFill: boolean;
initedFilled = false;
// 文件重新上传的位置标记,用以定位替换
reuploadIndex: undefined | number = undefined;
@ -439,7 +440,6 @@ export default class ImageControl extends React.Component<
const joinValues = props.joinValues;
const delimiter = props.delimiter as string;
let files: Array<FileValue> = [];
this.initAutoFill = !!(props.initAutoFill ?? true);
if (value) {
// files = (multiple && Array.isArray(value) ? value : joinValues ? (value as string).split(delimiter) : [value])
@ -488,11 +488,16 @@ export default class ImageControl extends React.Component<
}
componentDidMount() {
if (this.initAutoFill) {
const {formInited, addHook} = this.props;
formInited || !addHook
? this.syncAutoFill()
: addHook(this.syncAutoFill, 'init');
const {formInited, addHook} = this.props;
if (formInited || !addHook) {
this.initedFilled = true;
this.props.initAutoFill && this.syncAutoFill();
} else if (addHook) {
addHook(() => {
this.initedFilled = true;
this.props.initAutoFill && this.syncAutoFill();
}, 'init');
}
if (this.props.initCrop && this.files.length) {
@ -545,7 +550,9 @@ export default class ImageControl extends React.Component<
{
files: (this.files = files)
},
this.initAutoFill ? this.syncAutoFill : () => {}
props.changeMotivation !== 'formInited' && this.initedFilled
? this.syncAutoFill
: undefined
);
}
@ -1380,7 +1387,7 @@ export default class ImageControl extends React.Component<
},
() => {
if (!needUploading) {
this.onChange(false, true, this.initAutoFill);
this.onChange(false, true, this.props.initAutoFill);
}
}
);