ant-design/components/form/FormItemInput.tsx
zombieJ 4cdf37bedb
feat: New Form (#17327)
* init form

* first demo

* add normal login

* add style

* webit

* support nest errors

* beauti form errors

* use onReset

* modal demo

* add list demo

* match key of errors logic

* date demo

* customize component

* moving style

* add status style

* without form create

* add demos

* add inline style

* clean up legacy

* fix drawer demo

* mention

* fix edit-row

* editable table cell

* update mentions demo

* fix some test case

* fix upload test

* fix lint

* part of doc

* fix ts

* doc update

* rm react 15

* rm config

* enhance test coverage

* clean up

* fix FormItem context pass logic

* add more demo

* en to build

* update demo

* update demo & snapshot

* more doc

* update list doc

* update doc

* update demo to display condition render

* update snapshot

* add provider doc

* support configProvider

* more doc about validateMessages

* more description

* more and more doc

* fix typo

* en doc

* Form.List doc

* m v3 -> v4

* add skip
2019-07-03 20:14:39 +08:00

111 lines
3.0 KiB
TypeScript

import * as React from 'react';
import classNames from 'classnames';
import Icon from '../icon';
import CSSMotion from 'rc-animate/lib/CSSMotion';
import Col, { ColProps } from '../grid/col';
import { ValidateStatus } from './FormItem';
import { FormContext } from './context';
import { useCacheErrors } from './util';
interface FormItemInputMiscProps {
prefixCls: string;
children: React.ReactNode;
errors: React.ReactNode[];
touched: boolean;
validating: boolean;
hasFeedback?: boolean;
validateStatus?: ValidateStatus;
onDomErrorVisibleChange: (visible: boolean) => void;
}
export interface FormItemInputProps {
wrapperCol?: ColProps;
help?: React.ReactNode;
extra?: React.ReactNode;
}
function getIconType(validateStatus?: ValidateStatus) {
switch (validateStatus) {
case 'success':
return 'check-circle';
case 'warning':
return 'exclamation-circle';
case 'error':
return 'close-circle';
case 'validating':
return 'loading';
default:
return '';
}
}
const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = ({
prefixCls,
wrapperCol,
children,
errors,
onDomErrorVisibleChange,
hasFeedback,
validateStatus,
extra,
}) => {
const baseClassName = `${prefixCls}-item`;
const formContext = React.useContext(FormContext);
const mergedWrapperCol: ColProps = wrapperCol || formContext.wrapperCol || {};
const className = classNames(`${baseClassName}-control`, mergedWrapperCol.className);
const [visible, cacheErrors] = useCacheErrors(errors, changedVisible => {
if (changedVisible) {
onDomErrorVisibleChange(true);
}
});
// Should provides additional icon if `hasFeedback`
const iconType = getIconType(validateStatus);
const icon =
hasFeedback && iconType ? (
<span className={`${baseClassName}-children-icon`}>
<Icon type={iconType} theme={iconType === 'loading' ? 'outlined' : 'filled'} />
</span>
) : null;
// Pass to sub FormItem should not with col info
const subFormContext = { ...formContext };
delete subFormContext.labelCol;
delete subFormContext.wrapperCol;
return (
<FormContext.Provider value={subFormContext}>
<Col {...mergedWrapperCol} className={className}>
<div className={`${baseClassName}-control-input`}>
{children}
{icon}
</div>
<CSSMotion
visible={visible}
motionName="show-help"
onLeaveEnd={() => {
onDomErrorVisibleChange(false);
}}
motionAppear
removeOnLeave
>
{({ className: motionClassName }: { className: string }) => {
return (
<div className={classNames(`${baseClassName}-explain`, motionClassName)} key="help">
{cacheErrors}
</div>
);
}}
</CSSMotion>
{extra && <div className={`${baseClassName}-extra`}>{extra}</div>}
</Col>
</FormContext.Provider>
);
};
export default FormItemInput;