0.0.8 • Published 3 years ago

rhform v0.0.8

Weekly downloads
14
License
MIT
Repository
-
Last release
3 years ago

rhform

A form component. inspiration

中文

Installation

npm install rhform --save
# or
yarn add rhform

Reset

const store = new FormStore({ name: 'test' })
store.reset()

Validation

function assert(condition, message) {
  if (!condition) throw new Error(message)
}
const rules = {
  name: (val) => assert(!!val && !!val.trim(), 'Name is required'),
}
const store = new FormStore({}, rules)
// ...
try {
  const values = await store.validate()
  console.log('values:', values)
} catch (error) {
  console.log('error:', error)
}

Hook

function App() {
  const [store] = useFormStore(
    {
      username: 'Default',
      password: '',
      gender: 'male',
      contact: {
        phone: '1n2,mk8798y23,cLKJlk1',
        address: 'sdsdsd1',
        checkbox: [],
        radio: '',
      },
    },
    {
      username: {
        fn(v) {
          return new Promise((resolve, reject) => {
            setTimeout(() => {
              if (v === 'as') {
                reject('error这是一个错误')
              }
              //promise 验证方法, 必须明确结果, 不然验证会超时
              resolve()
            }, 1000)
          })
        },
      },
      radio: {
        fn(v) {
          if (v === 'radio1') {
            return '错误'
          }
        },
      },
    }
  )

  // console.log(store, '===+++==')

  const onReset = React.useCallback((e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
    console.log(JSON.stringify(store), 'reseted')
  }, [])

  const onSubmit = React.useCallback(async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
    console.log(JSON.stringify(store), 'submit')
  }, [])

  return (
    <Form
      as='form'
      store={store}
      onSubmit={onSubmit}
      onReset={onReset}
      inline={boolean('Inline', false)}
      labelWidth={number('Label Width', 120)}
      labelAlign={select('labelAlign', ['left', 'right', 'center'], 'left')}
      gutter={number('Gutter', 20)}
    >
      <Form.Item
        required={boolean('RequiredName', true)}
        error={store.error('username')}
        label='username'
      >
        <Form.Field type='text' name='username' rule={{ fn: 'required' }} loadingAs='loading...' />
        {store.get('username')}
      </Form.Item>
      <Form.Item
        required={boolean('RequiredRadioCheckbox', false)}
        label='radio checkbox'
        error={store.error('radio')}
      >
        <div>
          <Form.Field type='radio' name='radio' value='radio1' />
          <Form.Field type='radio' name='radio' value='radio2' />
          {store.get('radio')}
        </div>
        <Form.Field type='checkbox' name='checkbox' value='checkbox1' />
        <Form.Field type='checkbox' name='checkbox' value='checkbox2' />
        <Form.Field type='checkbox' name='checkbox' value='checkbox3' />
        {(Array.isArray(store.get('checkbox'))
          ? store.get('checkbox')
          : [store.get('checkbox')]
        ).map((i) => {
          return i
        })}
      </Form.Item>
      <Form.Item label='Gender' error={store.error('contact.phone')}>
        <Form.Field as='select' multiple name='select'>
          <option value='male'>Male</option>
          <option value='female'>Female</option>
          <option value='1d'>1d</option>
          <option value='czxc'>czxc</option>
          <option value='13f'>13f</option>
        </Form.Field>
        {(store.get('select') || []).map((i) => {
          return i
        })}
        <Form.Field as='select' name='select2'>
          <option value='male'>Male</option>
          <option value='female'>Female</option>
          <option value='1d'>1d</option>
          <option value='czxc'>czxc</option>
          <option value='13f'>13f</option>
        </Form.Field>
        {store.get('select2')}

        <select>
          <option value='male'>Male</option>
          <option value='female'>Female</option>
          <option value='1d'>1d</option>
          <option value='czxc'>czxc</option>
          <option value='13f'>13f</option>
        </select>
      </Form.Item>
      <Form.Item label='Phone'>
        <Form.Field name='Phone' type='text' />
        {store.get('Phone')}
      </Form.Item>
      <Form.Item label='Address'>
        <Form.Field name='Address' type='text' />
        {store.get('Address')}
      </Form.Item>
      <Form.Item label=''>
        <button
          type='button'
          onClick={() => {
            console.log('===button click==')
          }}
        >
          Button
        </button>
        <button type='submit'>Submit</button>
        <button type='reset'>Reset</button>
      </Form.Item>
    </Form>
  )
}

ComponentClass

class App extends React.Component {
  state: {
    aaa: string,
    store: any,
  }
  store: FormStoreInstance
  constructor(props) {
    super(props)
    this.state = {
      aaa: '',
      store: {
        checkbox: 'checkbox1',
        username: 'Default',
        password: '',
        gender: 'male',
        contact: {
          phone: '',
          address: 'sdsdsd1',
          checkbox: [],
          radio: '',
        },
      },
    }
    this.store = new FormStore(
      this.state.store,
      (value) => {
        this.setState({
          store: value,
        })
      },
      {
        username: {
          fn(v) {
            // if (v === 'as') {
            //   return 'error这是一个错误'
            // }
            // return true
            return new Promise((resolve, reject) => {
              setTimeout(() => {
                if (v === 'as') {
                  reject('error这是一个错误')
                }
                //promise 验证方法, 必须明确结果, 不然验证会超时
                resolve()
              }, 1000)
            })
          },
        },
      }
    )
  }
  onReset = (e) => {
    console.log(JSON.stringify(this.store), 'reseted')
  }
  onSubmit = async (e) => {
    console.log(JSON.stringify(this.store), 'submited')
  }
  render() {
    // console.log(this.store, '======')
    const store = this.store
    const onSubmit = this.onSubmit.bind(this)
    const onReset = this.onReset.bind(this)
    return (
      <Form
        as='form'
        store={store}
        onSubmit={onSubmit}
        onReset={onReset}
        inline={boolean('Inline', false)}
        labelWidth={number('Label Width', 120)}
        labelAlign={select('labelAlign', ['left', 'right', 'center'], 'left')}
        gutter={number('Gutter', 20)}
      >
        <Form.Item
          required={boolean('RequiredName', true)}
          error={store.error('username')}
          label='username'
        >
          <Form.Field
            type='text'
            name='username'
            rule={{ fn: 'required' }}
            loadingAs='loading...'
          />
          {store.get('username')}
        </Form.Item>
        <Form.Item
          required={boolean('RequiredRadioCheckbox', false)}
          label='radio checkbox'
          error={store.error('radio')}
        >
          <div>
            <Form.Field type='radio' name='radio' value='radio1' />
            <Form.Field type='radio' name='radio' value='radio2' />
            {store.get('radio')}
          </div>
          <Form.Field type='checkbox' name='checkbox' value='checkbox1' />
          <Form.Field type='checkbox' name='checkbox' value='checkbox2' />
          <Form.Field type='checkbox' name='checkbox' value='checkbox3' />
          {(Array.isArray(store.get('checkbox'))
            ? store.get('checkbox')
            : [store.get('checkbox')]
          ).map((i) => {
            return i
          })}
        </Form.Item>
        <Form.Item label='Gender' error={store.error('contact.phone')}>
          <Form.Field as='select' multiple name='select'>
            <option value='male'>Male</option>
            <option value='female'>Female</option>
            <option value='1d'>1d</option>
            <option value='czxc'>czxc</option>
            <option value='13f'>13f</option>
          </Form.Field>
          {(store.get('select') || []).map((i) => {
            return i
          })}
          <Form.Field as='select' name='select2'>
            <option value='male'>Male</option>
            <option value='female'>Female</option>
            <option value='1d'>1d</option>
            <option value='czxc'>czxc</option>
            <option value='13f'>13f</option>
          </Form.Field>
          {store.get('select2')}

          <select>
            <option value='male'>Male</option>
            <option value='female'>Female</option>
            <option value='1d'>1d</option>
            <option value='czxc'>czxc</option>
            <option value='13f'>13f</option>
          </select>
        </Form.Item>
        <Form.Item label='Phone'>
          <Form.Field name='Phone' type='text' />
          {store.get('Phone')}
        </Form.Item>
        <Form.Item label='Address'>
          <Form.Field name='Address' type='text' />
          {store.get('Address')}
        </Form.Item>
        <Form.Item label=''>
          <button
            type='button'
            onClick={() => {
              console.log('===button click==')
            }}
          >
            Button
          </button>
          <button type='submit'>Submit</button>
          <button type='reset'>Reset</button>
        </Form.Item>
      </Form>
    )
  }
}

APIs

<Form>

props

nametypedefaultdescriptionrequired
classNamestring''class namefalse
childrenReact.ReactNode''childrenfalse
storeFormStoreInstance''store instancetrue
asReact.ComponentType<any>;string;React.ComponentType;React.ForwardRefExoticComponent<any>'form'native elementfalse

events

nametypedefaultdescriptionrequired
onSubmit(e: React.FormEvent) => void''submitfalse
onReset(e: React.FormEvent) => void''resetfalse

<FormItem>

props

nametypedefaultdescriptionrequired
classNamestring''class namefalse
childrenReact.ReactNode''childrenfalse
labelstring''labelfalse
namestring''namefalse
requiredboolean''requiredfalse
labelWidthnumber''label widthfalse
labelAlignProperty.TextAlign''label alignfalse
errorany''errorfalse
suffixReact.ReactNode''errorfalse

<FormField>

props

nametypedefaultdescriptionrequired
as'input';'select';'textarea';FunctionComponent<P>;ComponentClass<P>;string'input'native elementfalse
childrenReact.ReactNode''childrenfalse
namestring''nametrue
valueKeystring''valueKeyfalse
valueGetterValueGetter''ValueGetterfalse
loadingAsFunctionComponent<any> ; ComponentClass<any> ; string''loading native elementfalse
typestring''typefalse
valueany''valuefalse
multipleboolean''multiplefalse
ruleRule ; Rule[]''rulefalse
validateTrigger'onChange' ; 'onBlur' ; string'onChange'validateTriggerfalse
validateTrigger'onChange' ; 'onBlur' ; string'onChange'validateTriggerfalse

FormStoreConstructor
interface FormStoreConstructor<T extends Object = any> {
  new (
    store: T,
    changed: React.Dispatch<React.SetStateAction<Partial<T>>>,
    rules?: Rules
  ): FormStoreInstance<T>
  validator: Record<string, ValidatorFn>
}
FormStoreInstance
interface FormStoreInstance<T extends Object = any> {
  store: T
  changed: React.Dispatch<React.SetStateAction<Partial<T>>>
  rules: Rules
  initialValues: T
  names: Record<string, number>
  errors: Record<string, ValidResult>
  validStacks: Record<string, (Promise<ValidResult> | ValidResult)[]>
  validLoadings: Record<string, boolean>
  addName(name: string): void
  removeName(name: string): void
  addRule(name: string, newRule: Rule): void
  removeRule(name: string, newRule: Rule): void
  initStore(v: T): T
  reset(): void
  has(name: string): boolean
  get(name?: string): any | undefined
  unset(name: string): void
  set<V>(name: string, v?: V, refresh?: boolean): void
  refresh(): void
  setLoading(name: string): void
  unsetLoading(name: string): void
  isLoading(name: string): boolean
  validate: DebouncedFunc<
    (
      name?: string | undefined,
      silent?: boolean | undefined
    ) => Promise<ValidResult>
  >
  setError(name: string, msg: string): void
  unsetError(name: string): void
  error(name: string): ValidResult
}

FormStoreConstructor.validator Inner Validator

  • 'password' (v: string, othername: string, { data })
  • 'required' (v: any, msg: string)
  • 'email' (v: any, msg: string)
  • 'ipv4' (v: any, msg: string)
  • 'url' (v: any, msg: string)
  • 'equals' (v: string, o: string)
  • 'username' (v: any, msg: string)
  • 'phone' (v: any, msg: string)
  • 'cn' (v: any, msg: string)
0.0.8

3 years ago

0.0.5

3 years ago

0.0.7

3 years ago

0.0.6

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago