Skip to content

mjolnirjs/stated-form-bean

Repository files navigation

stated-form-bean

Travis Codecov type-coverage npm GitHub release

David Peer David David Dev

Conventional Commits code style: prettier codechecks.io

React Form Binding via StatedBean

Install

# yarn
yarn add stated-bean yup stated-form-bean

yarn add @types/yup -D

# npm
npm i stated-bean yup stated-form-bean

npm i @types/yup -D

Usage

FormModel
import { StatedBean, Stated } from 'stated-bean';

import { Valid, FormModel } from 'stated-form-bean';
import * as yup from 'yup';

export interface User {
  name: string;
  age: number;
}

@StatedBean()
export class UserModel extends FormModel<UserModel> {
  @Stated()
  @Valid(
    yup.object().shape({
      name: yup.string().required(),
      age: yup
        .number()
        .min(10)
        .max(99)
        .required(),
    }),
    { validOnChange: false },
  )
  user: Partial<User> = { age: 15 };

  setUser(u: Partial<User>) {
    this.user = {
      ...this.user,
      ...u,
    };
  }
}
React Form
import { useStatedBean } from 'stated-bean';

import { UserModel } from './UserModel';

import * as React from 'react';

export const UserForm = () => {
  const model = useStatedBean(UserModel);

  const { errors } = model.getFormField('user');

  const handleSubmit = React.useCallback(
    async e => {
      e.preventDefault();
      console.log(model);
      const valid = await model.validate('user');
      if (valid) {
        alert('valid success');
      }
    },
    [model],
  );
  return (
    <div>
      <form>
        <div>
          <label>UserName:</label>
          <input
            type="text"
            value={model.user.name || ''}
            onChange={e => model.setUser({ name: e.target.value })}
          />
          <span>{errors && errors.name}</span>
        </div>
        <div>
          <label>Age:</label>
          <input
            type="number"
            min={10}
            max={99}
            value={model.user.age}
            onChange={e => model.setUser({ age: Number(e.target.value) })}
          />
          <span>{errors && errors.age}</span>
        </div>
        <button type="submit" onClick={handleSubmit}>
          Submit
        </button>
      </form>
    </div>
  );
};
FormValidatorInterceptor
const app = new StatedBeanApplication();

app.setInterceptors(new FormValidateInterceptor());

const App = () => {
  return (
    <StatedBeanProvider application={app} types={[]}>
      <UserForm />
    </StatedBeanProvider>
  );
};

License

MIT