feat: FormItem support _internalItemRender (#27881)

* feat: formitem support _internalItemRender

* add mark

* up rc-field-form

* fix ts error

* Update components/form/FormItemInput.tsx

Co-authored-by: 二货机器人 <smith3816@gmail.com>

* update notes

Co-authored-by: 二货机器人 <smith3816@gmail.com>
This commit is contained in:
陈帅 2020-11-20 07:43:43 -06:00 committed by GitHub
parent dfdea4c347
commit 95ce54ca79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 84 additions and 29 deletions

View File

@ -40,7 +40,7 @@ const LoadingIcon: React.FC<LoadingIconProps> = ({ prefixCls, loading, existIcon
onLeaveStart={getRealWidth}
onLeaveActive={getCollapsedWidth}
>
{({ className, style }: { className: string; style: React.CSSProperties }, ref: any) => {
{({ className, style }: { className?: string; style?: React.CSSProperties }, ref: any) => {
return (
<span className={`${prefixCls}-loading-icon`} style={style} ref={ref}>
<LoadingOutlined className={classNames(className)} />
@ -49,6 +49,6 @@ const LoadingIcon: React.FC<LoadingIconProps> = ({ prefixCls, loading, existIcon
}}
</CSSMotion>
);
}
};
export default LoadingIcon;

View File

@ -69,7 +69,7 @@ export default function ErrorList({
motionAppear
removeOnLeave
>
{({ className: motionClassName }: { className: string }) => {
{({ className: motionClassName }: { className?: string }) => {
return (
<div
className={classNames(

View File

@ -17,6 +17,20 @@ interface FormItemInputMiscProps {
hasFeedback?: boolean;
validateStatus?: ValidateStatus;
onDomErrorVisibleChange: (visible: boolean) => void;
/**
* @private Internal usage, do not use in any of your production.
*/
_internalItemRender?: {
mark: string;
render: (
props: FormItemInputProps & FormItemInputMiscProps,
domList: {
input: JSX.Element;
errorList: JSX.Element;
extra: JSX.Element | null;
},
) => React.ReactNode;
};
}
export interface FormItemInputProps {
@ -33,18 +47,20 @@ const iconMap: { [key: string]: any } = {
validating: LoadingOutlined,
};
const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = ({
prefixCls,
status,
wrapperCol,
children,
help,
errors,
onDomErrorVisibleChange,
hasFeedback,
validateStatus,
extra,
}) => {
const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = props => {
const {
prefixCls,
status,
wrapperCol,
children,
help,
errors,
onDomErrorVisibleChange,
hasFeedback,
_internalItemRender: formItemRender,
validateStatus,
extra,
} = props;
const baseClassName = `${prefixCls}-item`;
const formContext = React.useContext(FormContext);
@ -74,21 +90,36 @@ const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = ({
delete subFormContext.labelCol;
delete subFormContext.wrapperCol;
const inputDom = (
<div className={`${baseClassName}-control-input`}>
<div className={`${baseClassName}-control-input-content`}>{children}</div>
{icon}
</div>
);
const errorListDom = (
<FormItemPrefixContext.Provider value={{ prefixCls, status }}>
<ErrorList errors={errors} help={help} onDomErrorVisibleChange={onDomErrorVisibleChange} />
</FormItemPrefixContext.Provider>
);
// If extra = 0, && will goes wrong
// 0&&error -> 0
const extraDom = extra ? <div className={`${baseClassName}-extra`}>{extra}</div> : null;
const dom =
formItemRender && formItemRender.mark === 'pro_table_render' && formItemRender.render ? (
formItemRender.render(props, { input: inputDom, errorList: errorListDom, extra: extraDom })
) : (
<>
{inputDom}
{errorListDom}
{extraDom}
</>
);
return (
<FormContext.Provider value={subFormContext}>
<Col {...mergedWrapperCol} className={className}>
<div className={`${baseClassName}-control-input`}>
<div className={`${baseClassName}-control-input-content`}>{children}</div>
{icon}
</div>
<FormItemPrefixContext.Provider value={{ prefixCls, status }}>
<ErrorList
errors={errors}
help={help}
onDomErrorVisibleChange={onDomErrorVisibleChange}
/>
</FormItemPrefixContext.Provider>
{extra && <div className={`${baseClassName}-extra`}>{extra}</div>}
{dom}
</Col>
</FormContext.Provider>
);

View File

@ -2341,7 +2341,6 @@ exports[`renders ./components/form/demo/inline-login.md correctly 1`] = `
>
<button
class="ant-btn ant-btn-primary"
disabled=""
type="submit"
>
<span>

View File

@ -772,6 +772,31 @@ describe('Form', () => {
expect(wrapper.find('form').hasClass('ant-form-hide-required-mark')).toBeTruthy();
});
it('_internalItemRender api test', () => {
const wrapper = mount(
<Form>
<Form.Item
name="light"
_internalItemRender={{
mark: 'pro_table_render',
render: (_, doms) => {
return (
<div id="test">
{doms.input}
{doms.errorList}
{doms.extra}
</div>
);
},
}}
>
<input defaultValue="should warning" />
</Form.Item>
</Form>,
);
expect(wrapper.find('#test').exists()).toBeTruthy();
});
describe('tooltip', () => {
it('ReactNode', () => {
const wrapper = mount(

View File

@ -124,7 +124,7 @@
"rc-dialog": "~8.4.0",
"rc-drawer": "~4.1.0",
"rc-dropdown": "~3.2.0",
"rc-field-form": "~1.15.0",
"rc-field-form": "~1.17.0",
"rc-image": "~4.0.0",
"rc-input-number": "~6.1.0",
"rc-mentions": "~1.5.0",