mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 12:08:13 +08:00
form 改造
This commit is contained in:
parent
a3dbf4703a
commit
cee031d534
@ -334,7 +334,6 @@ const maybeFormItem = [
|
||||
'hbox',
|
||||
'panel',
|
||||
'service',
|
||||
'tabs',
|
||||
'anchor-nav'
|
||||
];
|
||||
|
||||
@ -385,23 +384,77 @@ function wrapControl(item: any) {
|
||||
};
|
||||
}
|
||||
|
||||
function controlToNormalRenderer(item: any) {
|
||||
return item && controlMapping[item.type]
|
||||
? {
|
||||
...item,
|
||||
type: controlMapping[item.type]
|
||||
}
|
||||
: ~maybeFormItem.indexOf(item?.type)
|
||||
? wrapControl(item)
|
||||
: item;
|
||||
}
|
||||
|
||||
addSchemaFilter(function (schema: Schema) {
|
||||
// controls 转成 body
|
||||
if (schema?.type === 'combo' && Array.isArray(schema.conditions)) {
|
||||
schema = {
|
||||
...schema,
|
||||
conditions: schema.conditions.map(condition => {
|
||||
if (Array.isArray(condition.controls)) {
|
||||
condition = {
|
||||
...condition,
|
||||
body: condition.controls.map(controlToNormalRenderer)
|
||||
};
|
||||
delete condition.controls;
|
||||
}
|
||||
|
||||
return condition;
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
if (Array.isArray(schema?.controls)) {
|
||||
schema = {
|
||||
...schema,
|
||||
body: schema?.controls.map(item =>
|
||||
item && controlMapping[item.type]
|
||||
? {
|
||||
...item,
|
||||
type: controlMapping[item.type]
|
||||
}
|
||||
: ~maybeFormItem.indexOf(item?.type)
|
||||
? wrapControl(item)
|
||||
: item
|
||||
[schema.type === 'combo' ? `items` : 'body']: schema?.controls.map(
|
||||
controlToNormalRenderer
|
||||
)
|
||||
};
|
||||
delete schema.controls;
|
||||
} else if (schema?.type === 'tabs' && Array.isArray(schema.tabs)) {
|
||||
schema = {
|
||||
...schema,
|
||||
tabs: schema.tabs.map(tab => {
|
||||
if (Array.isArray(tab.controls)) {
|
||||
tab = {
|
||||
...tab,
|
||||
body: tab?.controls.map(controlToNormalRenderer)
|
||||
};
|
||||
}
|
||||
|
||||
return tab;
|
||||
})
|
||||
};
|
||||
} else if (schema?.type === 'anchor-nav' && Array.isArray(schema.links)) {
|
||||
schema = {
|
||||
...schema,
|
||||
links: schema.links.map(link => {
|
||||
if (Array.isArray(link.controls)) {
|
||||
link = {
|
||||
...link,
|
||||
body: link?.controls.map(controlToNormalRenderer)
|
||||
};
|
||||
}
|
||||
|
||||
return link;
|
||||
})
|
||||
};
|
||||
} else if (schema?.type === 'input-array' && Array.isArray(schema.items)) {
|
||||
schema = {
|
||||
...schema,
|
||||
items: schema.items.map(controlToNormalRenderer)
|
||||
};
|
||||
}
|
||||
|
||||
return schema;
|
||||
|
@ -34,7 +34,7 @@ import {SchemaApi, SchemaClassName, SchemaIcon, SchemaTpl} from '../../Schema';
|
||||
|
||||
export type ComboCondition = {
|
||||
test: string;
|
||||
controls: Array<FormControlSchema>;
|
||||
body: Array<FormControlSchema>;
|
||||
label: string;
|
||||
scaffold?: any;
|
||||
mode?: string;
|
||||
@ -118,7 +118,7 @@ export interface ComboControlSchema extends FormBaseControl {
|
||||
/**
|
||||
* 数组输入框的子项
|
||||
*/
|
||||
controls?: Array<ComboSubControl>;
|
||||
items?: Array<ComboSubControl>;
|
||||
|
||||
/**
|
||||
* 是否可拖拽排序
|
||||
@ -319,7 +319,7 @@ export default class ComboControl extends React.Component<ComboProps> {
|
||||
'lazyLoad',
|
||||
'changeImmediately',
|
||||
'strictMode',
|
||||
'controls',
|
||||
'items',
|
||||
'conditions',
|
||||
'messages'
|
||||
];
|
||||
@ -931,7 +931,7 @@ export default class ComboControl extends React.Component<ComboProps> {
|
||||
translate: __
|
||||
} = this.props;
|
||||
|
||||
let controls = this.props.controls;
|
||||
let items = this.props.items;
|
||||
let value = this.props.value;
|
||||
|
||||
if (flat && typeof value === 'string') {
|
||||
@ -1029,18 +1029,18 @@ export default class ComboControl extends React.Component<ComboProps> {
|
||||
|
||||
if (Array.isArray(conditions) && conditions.length) {
|
||||
condition = this.pickCondition(data);
|
||||
controls = condition ? condition.controls : undefined;
|
||||
items = condition ? condition.body : undefined;
|
||||
}
|
||||
|
||||
let finnalControls =
|
||||
flat && controls
|
||||
flat && items
|
||||
? [
|
||||
{
|
||||
...(controls && controls[0]),
|
||||
...(items && items[0]),
|
||||
name: 'flat'
|
||||
}
|
||||
]
|
||||
: controls;
|
||||
: items;
|
||||
|
||||
const hasUnique =
|
||||
Array.isArray(finnalControls) &&
|
||||
@ -1082,7 +1082,7 @@ export default class ComboControl extends React.Component<ComboProps> {
|
||||
`multiple/${index}`,
|
||||
{
|
||||
type: 'form',
|
||||
controls: finnalControls,
|
||||
body: finnalControls,
|
||||
wrapperComponent: 'div',
|
||||
wrapWithPanel: false,
|
||||
mode: subFormMode,
|
||||
@ -1152,7 +1152,7 @@ export default class ComboControl extends React.Component<ComboProps> {
|
||||
translate: __
|
||||
} = this.props;
|
||||
|
||||
let controls = this.props.controls;
|
||||
let items = this.props.items;
|
||||
let value = this.props.value;
|
||||
|
||||
if (flat && typeof value === 'string') {
|
||||
@ -1210,18 +1210,18 @@ export default class ComboControl extends React.Component<ComboProps> {
|
||||
|
||||
if (Array.isArray(conditions) && conditions.length) {
|
||||
condition = this.pickCondition(data);
|
||||
controls = condition ? condition.controls : undefined;
|
||||
items = condition ? condition.body : undefined;
|
||||
}
|
||||
|
||||
let finnalControls =
|
||||
flat && controls
|
||||
flat && items
|
||||
? [
|
||||
{
|
||||
...(controls && controls[0]),
|
||||
...(items && items[0]),
|
||||
name: 'flat'
|
||||
}
|
||||
]
|
||||
: controls;
|
||||
: items;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -1265,7 +1265,7 @@ export default class ComboControl extends React.Component<ComboProps> {
|
||||
`multiple/${index}`,
|
||||
{
|
||||
type: 'form',
|
||||
controls: finnalControls,
|
||||
body: finnalControls,
|
||||
wrapperComponent: 'div',
|
||||
wrapWithPanel: false,
|
||||
mode: multiLine ? subFormMode : 'row',
|
||||
@ -1365,13 +1365,13 @@ export default class ComboControl extends React.Component<ComboProps> {
|
||||
translate: __
|
||||
} = this.props;
|
||||
|
||||
let controls = this.props.controls;
|
||||
let items = this.props.items;
|
||||
const data = isObject(value) ? this.formatValue(value) : this.defaultValue;
|
||||
let condition: ComboCondition | null = null;
|
||||
|
||||
if (Array.isArray(conditions) && conditions.length) {
|
||||
condition = this.pickCondition(data);
|
||||
controls = condition ? condition.controls : undefined;
|
||||
items = condition ? condition.body : undefined;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -1400,12 +1400,12 @@ export default class ComboControl extends React.Component<ComboProps> {
|
||||
) : null}
|
||||
|
||||
<div className={cx(`Combo-itemInner`)}>
|
||||
{controls ? (
|
||||
{items ? (
|
||||
render(
|
||||
'single',
|
||||
{
|
||||
type: 'form',
|
||||
controls,
|
||||
body: items,
|
||||
wrapperComponent: 'div',
|
||||
wrapWithPanel: false,
|
||||
mode: multiLine ? 'normal' : 'row',
|
||||
|
@ -10,7 +10,8 @@ import {
|
||||
isObject,
|
||||
guid,
|
||||
isEmpty,
|
||||
autobind
|
||||
autobind,
|
||||
getVariable
|
||||
} from '../../utils/helper';
|
||||
import {IIRendererStore, IRendererStore} from '../../store';
|
||||
import {ScopedContext, IScopedContext} from '../../Scoped';
|
||||
@ -177,7 +178,7 @@ export function warpControl<
|
||||
}
|
||||
|
||||
// 同步 value
|
||||
model.changeTmpValue(propValue);
|
||||
model.changeTmpValue(propValue ?? value);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -266,19 +267,43 @@ export function warpControl<
|
||||
);
|
||||
}
|
||||
|
||||
let modified = false;
|
||||
if (model && props.value !== prevProps.value) {
|
||||
if (props.value !== model.tmpValue) {
|
||||
model.changeTmpValue(props.value);
|
||||
modified = true;
|
||||
}
|
||||
} else if (
|
||||
model &&
|
||||
props.data !== prevProps.data &&
|
||||
(!model.emitedValue || model.emitedValue === model.tmpValue)
|
||||
) {
|
||||
model.changeEmitedValue(undefined);
|
||||
const value = getVariable(
|
||||
props.data,
|
||||
model.name,
|
||||
props.canAccessSuperData !== false
|
||||
);
|
||||
const prevValue = getVariable(
|
||||
prevProps.data,
|
||||
model.name,
|
||||
props.canAccessSuperData !== false
|
||||
);
|
||||
if (value !== prevValue && value !== model.tmpValue) {
|
||||
model.changeTmpValue(value);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
if (
|
||||
props.validateOnChange === true ||
|
||||
(props.validateOnChange !== false &&
|
||||
(form?.submited || (isAlive(model) && model.validated)))
|
||||
(props.formSubmited || (isAlive(model!) && model!.validated)))
|
||||
) {
|
||||
this.validate();
|
||||
} else if (props.validateOnChange === false) {
|
||||
model.reset();
|
||||
model!.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -440,19 +465,26 @@ export function warpControl<
|
||||
const {
|
||||
formStore: form,
|
||||
onChange,
|
||||
$schema: {name, onChange: onFormItemChange}
|
||||
$schema: {name, onChange: onFormItemChange},
|
||||
data,
|
||||
canAccessSuperData
|
||||
} = this.props;
|
||||
|
||||
if (!this.model) {
|
||||
return;
|
||||
}
|
||||
const value = this.model.tmpValue;
|
||||
const oldValue = this.model.value;
|
||||
const oldValue = getVariable(
|
||||
data,
|
||||
this.model.name,
|
||||
canAccessSuperData !== false
|
||||
);
|
||||
|
||||
if (oldValue === value) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.changeEmitedValue(value);
|
||||
onFormItemChange?.(value, oldValue, this.model, form);
|
||||
onChange?.(value, name!, submitOnChange === true);
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ export default class FieldSetControl extends React.Component<
|
||||
}
|
||||
|
||||
@Renderer({
|
||||
test: /(^|\/)form(?:.+)?\/control\/fieldSet$/i,
|
||||
test: /(^|\/)fieldSet$/i,
|
||||
weight: -100,
|
||||
name: 'fieldset'
|
||||
})
|
||||
|
@ -1331,7 +1331,8 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
controlWidth,
|
||||
resolveDefinitions,
|
||||
lazyChange,
|
||||
formLazyChange
|
||||
formLazyChange,
|
||||
canAccessSuperData
|
||||
} = props;
|
||||
|
||||
const subProps = {
|
||||
@ -1341,6 +1342,7 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
(control as Schema).type
|
||||
}-${key}`,
|
||||
formInited: form.inited,
|
||||
formSubmited: form.submited,
|
||||
formMode: mode,
|
||||
formHorizontal: horizontal,
|
||||
controlWidth,
|
||||
@ -1355,10 +1357,11 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
removeHook: this.removeHook,
|
||||
renderFormItems: this.renderFormItems,
|
||||
formPristine: form.pristine,
|
||||
value: (control as any)?.name
|
||||
? getVariable(form.data, (control as any)?.name)
|
||||
: (control as any)?.value,
|
||||
defaultValue: (control as any)?.value
|
||||
canAccessSuperData
|
||||
// value: (control as any)?.name
|
||||
// ? getVariable(form.data, (control as any)?.name, canAccessSuperData)
|
||||
// : (control as any)?.value,
|
||||
// defaultValue: (control as any)?.value
|
||||
};
|
||||
|
||||
let subSchema: any = {
|
||||
|
@ -7,7 +7,9 @@ import {
|
||||
autobind,
|
||||
isDisabled,
|
||||
isObject,
|
||||
createObject
|
||||
createObject,
|
||||
getVariable,
|
||||
getVariable
|
||||
} from '../utils/helper';
|
||||
import findIndex from 'lodash/findIndex';
|
||||
import {Tabs as CTabs, Tab} from '../components/Tabs';
|
||||
@ -170,6 +172,31 @@ export default class Tabs extends React.Component<TabsProps, TabsState> {
|
||||
|
||||
componentDidMount() {
|
||||
this.autoJumpToNeighbour(this.activeKey);
|
||||
|
||||
let {name, value, onChange, source, tabs, data} = this.props;
|
||||
|
||||
// 如果没有配置 name ,说明不需要同步表单值
|
||||
if (
|
||||
!name ||
|
||||
typeof onChange !== 'function' ||
|
||||
// 如果关联某个变量数据,则不启用
|
||||
source
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
value = value ?? getVariable(data, name);
|
||||
|
||||
// 如果有值,切到对应的 tab
|
||||
if (value && Array.isArray(tabs)) {
|
||||
const key = this.resolveKeyByValue(value);
|
||||
key !== undefined && this.handleSelect(key);
|
||||
} else {
|
||||
const tab = this.resolveTabByKey(this.activeKey);
|
||||
if (tab && value !== ((tab as any).value ?? tab.title)) {
|
||||
onChange((tab as any).value ?? tab.title, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(preProps: TabsProps, prevState: any) {
|
||||
@ -219,6 +246,62 @@ export default class Tabs extends React.Component<TabsProps, TabsState> {
|
||||
}
|
||||
|
||||
this.autoJumpToNeighbour(this.activeKey);
|
||||
|
||||
let {name, value, onChange, source, data} = this.props;
|
||||
|
||||
// 如果没有配置 name ,说明不需要同步表单值
|
||||
if (
|
||||
!name ||
|
||||
typeof onChange !== 'function' ||
|
||||
// 如果关联某个变量数据,则不启用
|
||||
source
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let key: any;
|
||||
value = value ?? getVariable(data, name);
|
||||
const prevValue =
|
||||
preProps.value ?? getVariable(preProps.data, preProps.name);
|
||||
if (
|
||||
value !== prevValue &&
|
||||
(key = this.resolveKeyByValue(value)) !== undefined &&
|
||||
key !== this.activeKey
|
||||
) {
|
||||
this.handleSelect(key);
|
||||
} else if (this.activeKey !== prevState.activeKey) {
|
||||
const tab = this.resolveTabByKey(this.activeKey);
|
||||
if (tab && value !== ((tab as any).value ?? tab.title)) {
|
||||
onChange((tab as any).value ?? tab.title, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolveTabByKey(key: any) {
|
||||
const tabs = this.props.tabs;
|
||||
|
||||
if (!Array.isArray(tabs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return find(tabs, (tab: TabSchema, index) =>
|
||||
tab.hash ? tab.hash === key : index === key
|
||||
);
|
||||
}
|
||||
|
||||
resolveKeyByValue(value: any) {
|
||||
const tabs = this.props.tabs;
|
||||
|
||||
if (!Array.isArray(tabs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tab: TabSchema = find(
|
||||
tabs,
|
||||
tab => ((tab as any).value ?? tab.title) === value
|
||||
) as TabSchema;
|
||||
|
||||
return tab && tab.hash ? tab.hash : tabs.indexOf(tab);
|
||||
}
|
||||
|
||||
@autobind
|
||||
@ -417,7 +500,7 @@ export default class Tabs extends React.Component<TabsProps, TabsState> {
|
||||
}
|
||||
|
||||
@Renderer({
|
||||
test: /(^|\/)tabs$/,
|
||||
type: 'tabs',
|
||||
name: 'tabs'
|
||||
})
|
||||
export class TabsRenderer extends Tabs {}
|
||||
|
@ -60,6 +60,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
|
||||
loading: false,
|
||||
required: false,
|
||||
tmpValue: types.frozen(),
|
||||
emitedValue: types.frozen(),
|
||||
rules: types.optional(types.frozen(), {}),
|
||||
messages: types.optional(types.frozen(), {}),
|
||||
errorData: types.optional(types.array(ErrorDetail), []),
|
||||
@ -789,6 +790,10 @@ export const FormItemStore = StoreNode.named('FormItemStore')
|
||||
self.tmpValue = value;
|
||||
}
|
||||
|
||||
function changeEmitedValue(value: any) {
|
||||
self.emitedValue = value;
|
||||
}
|
||||
|
||||
function addSubFormItem(item: IFormItemStore) {
|
||||
self.itemsRef.push(item.id);
|
||||
}
|
||||
@ -819,6 +824,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
|
||||
openDialog,
|
||||
closeDialog,
|
||||
changeTmpValue,
|
||||
changeEmitedValue,
|
||||
addSubFormItem,
|
||||
removeSubFormItem
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user