chore: 表单项的布局方式支持外部扩充 (#2333)

This commit is contained in:
liaoxuezhi 2021-07-29 18:56:00 +08:00 committed by GitHub
parent a0526cc7d8
commit eb4940b69c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 426 additions and 414 deletions

View File

@ -164,7 +164,7 @@ import './renderers/Code';
import Scoped, {ScopedContext} from './Scoped';
import {FormItem, registerFormItem} from './renderers/Form/Item';
import {FormItem, FormItemWrap, registerFormItem} from './renderers/Form/Item';
// 兼容旧版本用法
import './compat';
@ -209,6 +209,7 @@ export {
Renderer as Renderer,
RegisterStore,
FormItem,
FormItemWrap,
OptionsControl,
wrapFetcher,
buildApi,

View File

@ -444,7 +444,7 @@ export class FormItemWrap extends React.Component<FormItemProps> {
model.closeDialog();
}
renderControl() {
renderControl(): JSX.Element | null {
const {
inputClassName,
formItem: model,
@ -488,391 +488,74 @@ export class FormItemWrap extends React.Component<FormItemProps> {
return null;
}
renderHorizontal() {
let {
className,
classnames: cx,
description,
descriptionClassName,
captionClassName,
desc,
label,
labelClassName,
render,
required,
caption,
remark,
labelRemark,
env,
formItem: model,
renderLabel,
renderDescription,
hint,
data,
showErrorMsg
} = this.props;
/**
*
*/
static layoutRenderers: {
[propsName: string]: (
props: FormItemProps,
renderControl: () => JSX.Element | null
) => JSX.Element;
} = {
horizontal: (props: FormItemProps, renderControl: () => JSX.Element) => {
let {
className,
classnames: cx,
description,
descriptionClassName,
captionClassName,
desc,
label,
labelClassName,
render,
required,
caption,
remark,
labelRemark,
env,
formItem: model,
renderLabel,
renderDescription,
hint,
data,
showErrorMsg
} = props;
// 强制不渲染 label 的话
if (renderLabel === false) {
label = label === false ? false : '';
}
// 强制不渲染 label 的话
if (renderLabel === false) {
label = label === false ? false : '';
}
description = description || desc;
const horizontal = this.props.horizontal || this.props.formHorizontal || {};
const left = getWidthRate(horizontal.left);
const right = getWidthRate(horizontal.right);
return (
<div
data-role="form-item"
className={cx(`Form-item Form-item--horizontal`, className, {
[`is-error`]: model && !model.valid,
[`is-required`]: required
})}
>
{label !== false ? (
<label
className={cx(
`Form-label`,
{
[`Form-itemColumn--${
typeof horizontal.leftFixed === 'string'
? horizontal.leftFixed
: 'normal'
}`]: horizontal.leftFixed,
[`Form-itemColumn--${left}`]: !horizontal.leftFixed
},
labelClassName
)}
>
<span>
{label ? render('label', filter(label, data)) : null}
{required && (label || labelRemark) ? (
<span className={cx(`Form-star`)}>*</span>
) : null}
{labelRemark
? render('label-remark', {
type: 'remark',
icon: labelRemark.icon || 'warning-mark',
tooltip: labelRemark,
className: cx(`Form-labelRemark`),
container: this.props.popOverContainer
? this.props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
</span>
</label>
) : null}
description = description || desc;
const horizontal = props.horizontal || props.formHorizontal || {};
const left = getWidthRate(horizontal.left);
const right = getWidthRate(horizontal.right);
return (
<div
className={cx(`Form-value`, {
// [`Form-itemColumn--offset${getWidthRate(horizontal.offset)}`]: !label && label !== false,
[`Form-itemColumn--${right}`]:
!horizontal.leftFixed && !!right && right !== 12 - left
data-role="form-item"
className={cx(`Form-item Form-item--horizontal`, className, {
[`is-error`]: model && !model.valid,
[`is-required`]: required
})}
>
{this.renderControl()}
{caption
? render('caption', caption, {
className: cx(`Form-caption`, captionClassName)
})
: null}
{remark
? render('remark', {
type: 'remark',
icon: remark.icon || 'warning-mark',
tooltip: remark,
className: cx(`Form-remark`),
container: this.props.popOverContainer
? this.props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
{hint && model && model.isFocused
? render('hint', hint, {
className: cx(`Form-hint`)
})
: null}
{model &&
!model.valid &&
showErrorMsg !== false &&
Array.isArray(model.errors) ? (
<ul className={cx(`Form-feedback`)}>
{model.errors.map((msg: string, key: number) => (
<li key={key}>{msg}</li>
))}
</ul>
) : null}
{renderDescription !== false && description
? render('description', description, {
className: cx(`Form-description`, descriptionClassName)
})
: null}
</div>
</div>
);
}
renderNormal() {
let {
className,
classnames: cx,
desc,
description,
label,
labelClassName,
render,
required,
caption,
remark,
labelRemark,
env,
descriptionClassName,
captionClassName,
formItem: model,
renderLabel,
renderDescription,
hint,
data,
showErrorMsg
} = this.props;
description = description || desc;
return (
<div
data-role="form-item"
className={cx(`Form-item Form-item--normal`, className, {
'is-error': model && !model.valid,
[`is-required`]: required
})}
>
{label && renderLabel !== false ? (
<label className={cx(`Form-label`, labelClassName)}>
<span>
{label ? render('label', filter(label, data)) : null}
{required && (label || labelRemark) ? (
<span className={cx(`Form-star`)}>*</span>
) : null}
{labelRemark
? render('label-remark', {
type: 'remark',
icon: labelRemark.icon || 'warning-mark',
tooltip: labelRemark,
className: cx(`Form-lableRemark`),
container: this.props.popOverContainer
? this.props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
</span>
</label>
) : null}
{this.renderControl()}
{caption
? render('caption', caption, {
className: cx(`Form-caption`, captionClassName)
})
: null}
{remark
? render('remark', {
type: 'remark',
icon: remark.icon || 'warning-mark',
className: cx(`Form-remark`),
tooltip: remark,
container:
env && env.getModalContainer ? env.getModalContainer : undefined
})
: null}
{hint && model && model.isFocused
? render('hint', hint, {
className: cx(`Form-hint`)
})
: null}
{model &&
!model.valid &&
showErrorMsg !== false &&
Array.isArray(model.errors) ? (
<ul className={cx(`Form-feedback`)}>
{model.errors.map((msg: string, key: number) => (
<li key={key}>{msg}</li>
))}
</ul>
) : null}
{renderDescription !== false && description
? render('description', description, {
className: cx(`Form-description`, descriptionClassName)
})
: null}
</div>
);
}
renderInline() {
let {
className,
classnames: cx,
desc,
description,
label,
labelClassName,
render,
required,
caption,
descriptionClassName,
captionClassName,
formItem: model,
remark,
labelRemark,
env,
hint,
renderLabel,
renderDescription,
data,
showErrorMsg
} = this.props;
description = description || desc;
return (
<div
data-role="form-item"
className={cx(`Form-item Form-item--inline`, className, {
'is-error': model && !model.valid,
[`is-required`]: required
})}
>
{label && renderLabel !== false ? (
<label className={cx(`Form-label`, labelClassName)}>
<span>
{label ? render('label', filter(label, data)) : label}
{required && (label || labelRemark) ? (
<span className={cx(`Form-star`)}>*</span>
) : null}
{labelRemark
? render('label-remark', {
type: 'remark',
icon: labelRemark.icon || 'warning-mark',
tooltip: labelRemark,
className: cx(`Form-lableRemark`),
container: this.props.popOverContainer
? this.props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
</span>
</label>
) : null}
<div className={cx(`Form-value`)}>
{this.renderControl()}
{caption
? render('caption', caption, {
className: cx(`Form-caption`, captionClassName)
})
: null}
{remark
? render('remark', {
type: 'remark',
icon: remark.icon || 'warning-mark',
className: cx(`Form-remark`),
tooltip: remark,
container: this.props.popOverContainer
? this.props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
{hint && model && model.isFocused
? render('hint', hint, {
className: cx(`Form-hint`)
})
: null}
{model &&
!model.valid &&
showErrorMsg !== false &&
Array.isArray(model.errors) ? (
<ul className={cx(`Form-feedback`)}>
{model.errors.map((msg: string, key: number) => (
<li key={key}>{msg}</li>
))}
</ul>
) : null}
{renderDescription !== false && description
? render('description', description, {
className: cx(`Form-description`, descriptionClassName)
})
: null}
</div>
</div>
);
}
renderRow() {
let {
className,
classnames: cx,
desc,
description,
label,
labelClassName,
render,
required,
caption,
remark,
labelRemark,
env,
descriptionClassName,
captionClassName,
formItem: model,
renderLabel,
renderDescription,
hint,
data,
showErrorMsg
} = this.props;
description = description || desc;
return (
<div
data-role="form-item"
className={cx(`Form-item Form-item--row`, className, {
'is-error': model && !model.valid,
[`is-required`]: required
})}
>
<div className={cx('Form-rowInner')}>
{label && renderLabel !== false ? (
<label className={cx(`Form-label`, labelClassName)}>
{label !== false ? (
<label
className={cx(
`Form-label`,
{
[`Form-itemColumn--${
typeof horizontal.leftFixed === 'string'
? horizontal.leftFixed
: 'normal'
}`]: horizontal.leftFixed,
[`Form-itemColumn--${left}`]: !horizontal.leftFixed
},
labelClassName
)}
>
<span>
{render('label', filter(label, data))}
{label ? render('label', filter(label, data)) : null}
{required && (label || labelRemark) ? (
<span className={cx(`Form-star`)}>*</span>
) : null}
@ -881,9 +564,9 @@ export class FormItemWrap extends React.Component<FormItemProps> {
type: 'remark',
icon: labelRemark.icon || 'warning-mark',
tooltip: labelRemark,
className: cx(`Form-lableRemark`),
container: this.props.popOverContainer
? this.props.popOverContainer
className: cx(`Form-labelRemark`),
container: props.popOverContainer
? props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
@ -893,7 +576,121 @@ export class FormItemWrap extends React.Component<FormItemProps> {
</label>
) : null}
{this.renderControl()}
<div
className={cx(`Form-value`, {
// [`Form-itemColumn--offset${getWidthRate(horizontal.offset)}`]: !label && label !== false,
[`Form-itemColumn--${right}`]:
!horizontal.leftFixed && !!right && right !== 12 - left
})}
>
{renderControl()}
{caption
? render('caption', caption, {
className: cx(`Form-caption`, captionClassName)
})
: null}
{remark
? render('remark', {
type: 'remark',
icon: remark.icon || 'warning-mark',
tooltip: remark,
className: cx(`Form-remark`),
container: props.popOverContainer
? props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
{hint && model && model.isFocused
? render('hint', hint, {
className: cx(`Form-hint`)
})
: null}
{model &&
!model.valid &&
showErrorMsg !== false &&
Array.isArray(model.errors) ? (
<ul className={cx(`Form-feedback`)}>
{model.errors.map((msg: string, key: number) => (
<li key={key}>{msg}</li>
))}
</ul>
) : null}
{renderDescription !== false && description
? render('description', description, {
className: cx(`Form-description`, descriptionClassName)
})
: null}
</div>
</div>
);
},
normal: (props: FormItemProps, renderControl: () => JSX.Element) => {
let {
className,
classnames: cx,
desc,
description,
label,
labelClassName,
render,
required,
caption,
remark,
labelRemark,
env,
descriptionClassName,
captionClassName,
formItem: model,
renderLabel,
renderDescription,
hint,
data,
showErrorMsg
} = props;
description = description || desc;
return (
<div
data-role="form-item"
className={cx(`Form-item Form-item--normal`, className, {
'is-error': model && !model.valid,
[`is-required`]: required
})}
>
{label && renderLabel !== false ? (
<label className={cx(`Form-label`, labelClassName)}>
<span>
{label ? render('label', filter(label, data)) : null}
{required && (label || labelRemark) ? (
<span className={cx(`Form-star`)}>*</span>
) : null}
{labelRemark
? render('label-remark', {
type: 'remark',
icon: labelRemark.icon || 'warning-mark',
tooltip: labelRemark,
className: cx(`Form-lableRemark`),
container: props.popOverContainer
? props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
</span>
</label>
) : null}
{renderControl()}
{caption
? render('caption', caption, {
@ -913,33 +710,248 @@ export class FormItemWrap extends React.Component<FormItemProps> {
: undefined
})
: null}
{hint && model && model.isFocused
? render('hint', hint, {
className: cx(`Form-hint`)
})
: null}
{model &&
!model.valid &&
showErrorMsg !== false &&
Array.isArray(model.errors) ? (
<ul className={cx(`Form-feedback`)}>
{model.errors.map((msg: string, key: number) => (
<li key={key}>{msg}</li>
))}
</ul>
) : null}
{renderDescription !== false && description
? render('description', description, {
className: cx(`Form-description`, descriptionClassName)
})
: null}
</div>
);
},
{hint && model && model.isFocused
? render('hint', hint, {
className: cx(`Form-hint`)
})
: null}
inline: (props: FormItemProps, renderControl: () => JSX.Element) => {
let {
className,
classnames: cx,
desc,
description,
label,
labelClassName,
render,
required,
caption,
descriptionClassName,
captionClassName,
formItem: model,
remark,
labelRemark,
env,
hint,
renderLabel,
renderDescription,
data,
showErrorMsg
} = props;
{model &&
!model.valid &&
showErrorMsg !== false &&
Array.isArray(model.errors) ? (
<ul className={cx('Form-feedback')}>
{model.errors.map((msg: string, key: number) => (
<li key={key}>{msg}</li>
))}
</ul>
) : null}
description = description || desc;
{description && renderDescription !== false
? render('description', description, {
className: cx(`Form-description`, descriptionClassName)
})
: null}
</div>
);
}
return (
<div
data-role="form-item"
className={cx(`Form-item Form-item--inline`, className, {
'is-error': model && !model.valid,
[`is-required`]: required
})}
>
{label && renderLabel !== false ? (
<label className={cx(`Form-label`, labelClassName)}>
<span>
{label ? render('label', filter(label, data)) : label}
{required && (label || labelRemark) ? (
<span className={cx(`Form-star`)}>*</span>
) : null}
{labelRemark
? render('label-remark', {
type: 'remark',
icon: labelRemark.icon || 'warning-mark',
tooltip: labelRemark,
className: cx(`Form-lableRemark`),
container: props.popOverContainer
? props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
</span>
</label>
) : null}
<div className={cx(`Form-value`)}>
{renderControl()}
{caption
? render('caption', caption, {
className: cx(`Form-caption`, captionClassName)
})
: null}
{remark
? render('remark', {
type: 'remark',
icon: remark.icon || 'warning-mark',
className: cx(`Form-remark`),
tooltip: remark,
container: props.popOverContainer
? props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
{hint && model && model.isFocused
? render('hint', hint, {
className: cx(`Form-hint`)
})
: null}
{model &&
!model.valid &&
showErrorMsg !== false &&
Array.isArray(model.errors) ? (
<ul className={cx(`Form-feedback`)}>
{model.errors.map((msg: string, key: number) => (
<li key={key}>{msg}</li>
))}
</ul>
) : null}
{renderDescription !== false && description
? render('description', description, {
className: cx(`Form-description`, descriptionClassName)
})
: null}
</div>
</div>
);
},
row: (props: FormItemProps, renderControl: () => JSX.Element) => {
let {
className,
classnames: cx,
desc,
description,
label,
labelClassName,
render,
required,
caption,
remark,
labelRemark,
env,
descriptionClassName,
captionClassName,
formItem: model,
renderLabel,
renderDescription,
hint,
data,
showErrorMsg
} = props;
description = description || desc;
return (
<div
data-role="form-item"
className={cx(`Form-item Form-item--row`, className, {
'is-error': model && !model.valid,
[`is-required`]: required
})}
>
<div className={cx('Form-rowInner')}>
{label && renderLabel !== false ? (
<label className={cx(`Form-label`, labelClassName)}>
<span>
{render('label', filter(label, data))}
{required && (label || labelRemark) ? (
<span className={cx(`Form-star`)}>*</span>
) : null}
{labelRemark
? render('label-remark', {
type: 'remark',
icon: labelRemark.icon || 'warning-mark',
tooltip: labelRemark,
className: cx(`Form-lableRemark`),
container: props.popOverContainer
? props.popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
</span>
</label>
) : null}
{renderControl()}
{caption
? render('caption', caption, {
className: cx(`Form-caption`, captionClassName)
})
: null}
{remark
? render('remark', {
type: 'remark',
icon: remark.icon || 'warning-mark',
className: cx(`Form-remark`),
tooltip: remark,
container:
env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
</div>
{hint && model && model.isFocused
? render('hint', hint, {
className: cx(`Form-hint`)
})
: null}
{model &&
!model.valid &&
showErrorMsg !== false &&
Array.isArray(model.errors) ? (
<ul className={cx('Form-feedback')}>
{model.errors.map((msg: string, key: number) => (
<li key={key}>{msg}</li>
))}
</ul>
) : null}
{description && renderDescription !== false
? render('description', description, {
className: cx(`Form-description`, descriptionClassName)
})
: null}
</div>
);
}
};
render() {
const {formMode, inputOnly, wrap, render, formItem: model} = this.props;
@ -949,15 +961,14 @@ export class FormItemWrap extends React.Component<FormItemProps> {
return this.renderControl();
}
const renderLayout =
FormItemWrap.layoutRenderers[mode] ||
FormItemWrap.layoutRenderers['normal'];
return (
<>
{mode === 'inline'
? this.renderInline()
: mode === 'horizontal'
? this.renderHorizontal()
: mode === 'row'
? this.renderRow()
: this.renderNormal()}
{renderLayout(this.props, this.renderControl.bind(this))}
{model
? render(
'modal',