import React from 'react'; import cx from 'classnames'; import bem from '../utils/bem'; import { FormContext, FormContextValue } from './context'; import FormItem from './FormItem'; import toBeField from './to-be-field'; const b = bem('rdf-form'); export interface FormValidator { required?: boolean; min?: number; max?: number; message?: string; trigger?: 'change' | 'blur' | 'none'; custom?: ( propValue: any, value: NonNullable ) => boolean | string | undefined; } export interface FormProps { value?: Record; validators?: Record; labelPosition?: 'left' | 'right' | 'top'; labelWidth?: number | string; labelHeight?: number | string; onSubmit?: (valid: boolean) => void; className?: string; style?: React.CSSProperties; } export class Form extends React.Component { static Item: typeof FormItem; static toBeField: typeof toBeField; static defaultProps: FormProps = { labelPosition: 'right', labelWidth: '100px', labelHeight: '32px', }; items: FormItem[] = []; addItem = (item: FormItem) => { this.items.push(item); }; removeItem = (item: FormItem) => { const index = this.items.indexOf(item); if (index >= 0) { this.items.splice(index, 1); } }; reset() { return this.items.reduce((prev, cur) => { return { ...prev, ...cur }; }, {}); } validate() { return this.items.some(item => !item.validate()); } handleSubmit = (ev: React.SyntheticEvent) => { ev.preventDefault(); const { onSubmit } = this.props; if (onSubmit) { onSubmit(this.validate()); } }; render() { const { value, validators, labelPosition, labelWidth, labelHeight, className, style, children, } = this.props; const contextValue: FormContextValue = { value, validators, labelPosition, labelWidth, labelHeight, addItem: this.addItem, removeItem: this.removeItem, }; const cls = cx(className, b(), [b([`label-${labelPosition}`])]); return (
{children}
); } } export default Form;