packages/form-render/src/render-core/FieldItem/main.tsx (212 lines of code) (raw):
import React, { createContext, useContext, useRef, useEffect } from 'react';
import { Form, Col, Row } from 'antd';
import { useStore } from 'zustand';
import classnames from 'classnames';
import { isCheckBoxType, _get } from '../../utils';
import { getWidgetName, getWidget } from '../../models/mapping';
import { getFormItemLayout } from '../../models/layout';
import getRuleList from '../../models/validates';
const UpperContext: any = createContext(() => {});
const valuePropNameMap = {
checkbox: 'checked',
switch: 'checked',
Checkbox: 'checked',
Switch: 'checked'
};
import {
FieldWrapper,
FieldWrapperStatus
} from './field';
import {
getParamValue,
getFieldProps,
getPath,
getLabel,
getColSpan,
getExtraView,
getTooltip
} from './module';
export default (props: any) => {
const { configCtx, store, schema, path, children, dependValues, rootPath } = props;
const fieldRef: any = useRef(null);
const formCtx: any = useStore(store, (state: any) => state.context);
const upperCtx: any = useContext(UpperContext);
const { form, widgets, methods, globalProps } = configCtx;
const {
reserveLabel,
hidden,
properties,
dependencies,
inlineMode: _inlineMode,
remove,
removeText,
visible = true,
...otherSchema
} = schema;
const getValueFromKey = getParamValue(formCtx, upperCtx, schema);
const widgetName = getWidgetName(schema);
let Widget = getWidget(widgetName, widgets);
const fieldProps = getFieldProps(widgetName, schema, {
widgets,
methods,
form,
dependValues,
globalProps,
path: getPath(path),
rootPath,
fieldRef
});
useEffect(() => {
form.setFieldRef(fieldProps.addons.dataPath, fieldRef);
}, []);
if (schema?.hidden) {
return null;
}
// Component not found
if (!widgetName) {
const ErrorSchema = widgets['errorSchema'] || widgets['ErrorSchema'];
return <ErrorSchema schema={schema} />;
}
if (schema.type === 'void') {
return (
<Col span={24}>
<Widget {...fieldProps } />
</Col>
);
}
const displayType = getValueFromKey('displayType');
let inlineSelf = _inlineMode || upperCtx?.displayType === 'inline';
// inexistence containers
if (!upperCtx.exist) {
inlineSelf = _inlineMode || formCtx?.displayType === 'inline';
}
const inlineChild = displayType === 'inline';
const labelWidth = getValueFromKey('labelWidth');
// Render Container Components
if (children) {
let childElement = (
<div className='fr-inline-container'>
{children}
</div>
);
if (!inlineChild) {
const gutter = { row: 16, column: 24 }[displayType];
childElement = (
<Row gutter={gutter}>
{children}
</Row>
);
}
fieldProps.children = childElement;
const content = <Widget labelWidth={labelWidth} displayType={schema.displayType} {...fieldProps} {...otherSchema} />;
return (
<UpperContext.Provider
value={{
column: schema.column,
labelCol: schema.labelCol,
fieldCol: schema.fieldCol,
displayType: schema.displayType,
labelWidth: schema.labelWidth,
noStyle: schema.noStyle,
exist: true,
}}
>
{inlineSelf ? content : <Col span={24} className={classnames('fr-obj-col', { [schema.className] : !!schema.className })}>{content}</Col>}
</UpperContext.Provider>
);
}
// Render field components
let label = getLabel(schema, displayType, widgets, fieldProps.addons);
let noStyle = getValueFromKey('noStyle');
const span = getColSpan(formCtx, upperCtx, schema);
const extra = getExtraView('extra', schema, widgets, fieldProps.addons);
const help = getExtraView('help', schema, widgets, fieldProps.addons);
const action = getExtraView('action', schema, widgets, fieldProps.addons);
const tooltip = getTooltip(schema, displayType);
const ruleList = getRuleList(schema, form, methods, fieldRef);
const readOnly = getValueFromKey('readOnly');
const disabled = getValueFromKey('disabled');
const validateTrigger = getValueFromKey('validateTrigger');
const _labelCol = getValueFromKey('labelCol');
const _fieldCol = getValueFromKey('fieldCol');
const maxWidth = getValueFromKey('maxWidth');
const { labelCol, fieldCol } = getFormItemLayout(Math.floor(24 / span * 1), schema, { displayType, labelWidth, _labelCol, _fieldCol });
const valuePropName = schema.valuePropName || valuePropNameMap[widgetName] || undefined;
if (readOnly) {
fieldProps.readOnly = readOnly;
}
if (disabled) {
fieldProps.disabled = disabled;
}
if (reserveLabel && !label && displayType !== 'column') {
label = 'fr-hide-label';
}
if (readOnly) {
Widget = widgets[schema.readOnlyWidget] || widgets['Html'];
}
// checkbox 布局有点特殊
if (isCheckBoxType(schema, readOnly)) {
fieldProps.title = label;
label = null;
if (displayType === 'row') {
label = 'fr-hide-label';
}
}
const initialValue = schema.default ?? schema.defaultValue;
const classRest = { 'fr-hide-label': label === 'fr-hide-label', 'fr-inline-field': inlineSelf, 'fr-field-visibility': !visible, [schema.className] : !! schema.className };
const formItem = (
<Form.Item
className={classnames('fr-field', classRest)}
label={label}
name={path}
valuePropName={valuePropName}
rules={readOnly ? [] : ruleList}
hidden={hidden}
tooltip={tooltip}
extra={extra}
help={help}
initialValue={initialValue}
labelCol={labelCol}
wrapperCol={fieldCol}
noStyle={noStyle}
dependencies={dependencies}
validateTrigger={ validateTrigger ?? (fieldRef?.current?.validator ? 'onSubmit' : 'onChange') }
>
{fieldProps.onStatusChange ? (
<FieldWrapperStatus
Field={Widget}
fieldProps={fieldProps}
maxWidth={maxWidth}
initialValue={initialValue}
acitonRender={action ? () => action : undefined}
/>
) : (
<FieldWrapper
Field={Widget}
fieldProps={fieldProps}
maxWidth={maxWidth}
initialValue={initialValue}
acitonRender={action ? () => action : undefined}
/>
)}
</Form.Item>
);
if (inlineSelf) {
if (noStyle) {
return (
<div
className={classnames('fr-inline-field', { 'fr-field-visibility': !visible, [schema.className] : !! schema.className })}
>
{formItem}
</div>
);
}
return formItem;
}
return (
<Col
span={span}
className={classnames(null, { 'fr-field-visibility': !visible })}
>
{formItem}
</Col>
);
}