@enfometa/em-forms Samples

These samples has basic implementation for @enfometa/em-forms

Github sample's repos

em-forms-samples

forms-validation

Introduction

A simple, robust and flexible react forms validation library for both React Js and React Native. The great thing about the library is, it has no dependency on the UI. You can easily decouple your business logic from the UI and can reuse in both React Js and React Native apps.

Samples

This section includes code samples for em-forms

Configuration in App.js file

This will register controls to specify how em-forms should deal with each control wrapped in EmFormControl

import { emFormsGlobalConfig } from "@enfometa/em-forms";
emFormsGlobalConfig.registerEmFormControls([
  {
    valuePropName: "value",
    onChangePropName: "onChange",
    valueFunc: (e) => e.target.value,
    controls: [{ type: "input" }],
  },
  {
    valuePropName: "value",
    onChangePropName: "onChange",
    valueFunc: (e) => e.target.value,
    controls: [{ type: "select" }],
  },
  {
    valuePropName: "checked",
    onChangePropName: "onChange",
    valueFunc: (e) => e.target.checked,
    controls: [
      {
        type: "input",
        props: { type: "checkbox" },
      },
    ],
  },
  {
    valuePropName: "selectedValue",
    onChangePropName: "onChange",
    valueFunc: (e) => e.target.value,
    controls: [{ type: "RadioGroup" }],
  },
]);

Use with functional component without using FormGroup component

import React from "react";
import { useEmForms, required, email, EmFormErrorMessage } from "@enfometa/em-forms";

const LoginWithoutFormsGroup = (props) => {
  const forms = useEmForms({
    forms: [
      {
        name: "username",
        value: "",
        validators: [
          { name: "required", func: required, message: "Username is required" },
          { name: "email", func: email, message: "Invalid email address" },
        ],
      },
      {
        name: "password",
        value: "",
        validators: [{ name: "required", func: required, message: "Password is required" }],
      },
      {
        name: "rememberMe",
        value: false,
      },
    ],
  });

  const login = () => {
    if (forms.validate()) {
      const model = forms.toModel();
      //do something with the model
      console.log(model);
    }
  };

  const reset = () => {
    forms.reset();
  };

  const updateFormValue = (formName, value) => {
    forms.setFormValue(formName, value);
  };

  const setFormTouch = (formName) => {
    forms.setFormTouch(formName, true);
  };

  return (
    <div className="container">
      <main>
        <div className="row g-5">
          <div className="col-md-6 col-lg-4">
            <h4 className="mb-3">Functional component Login without FormGroup</h4>
            <div className="row g-3">
              <div className="col-12">
                <input
                  type="email"
                  className="form-control"
                  placeholder="Email"
                  onChange={(e) => updateFormValue("username", e.target.value)}
                  value={forms.getFormValue("username")}
                  onBlur={(e) => setFormTouch("username")}
                />
                <div className="error-message">
                  <EmFormErrorMessage emForms={forms} formName="username" validatorName="required" />
                  <EmFormErrorMessage emForms={forms} formName="username" validatorName="email" />
                </div>
              </div>
              <div className="col-12">
                <input
                  type="password"
                  className="form-control"
                  placeholder="password"
                  onChange={(e) => updateFormValue("password", e.target.value)}
                  value={forms.getFormValue("password")}
                  onBlur={(e) => setFormTouch("password")}
                />
                <div className="error-message">
                  <EmFormErrorMessage emForms={forms} formName="password" validatorName="required" />
                </div>
              </div>
              <div className="col-12">
                <input
                  type="checkbox"
                  onChange={(e) => updateFormValue("rememberMe", e.target.checked)}
                  checked={forms.getFormValue("rememberMe")}
                  onBlur={(e) => setFormTouch("rememberMe")}
                />
              </div>

              <button className="w-100 btn btn-primary btn-lg" type="button" onClick={login}>
                Login
              </button>
              <button className="w-100 btn btn-primary btn-lg" type="button" onClick={reset}>
                Reset
              </button>
            </div>
          </div>
        </div>
      </main>
    </div>
  );
};

export default LoginWithoutFormsGroup;

reset() function can be called in three ways:

  • forms.reset() : Reset all vlaues to default values (Initial values)

  • forms.reset(values?: ResetConfig[]): This accepts an array of ResetConfig object. If you want a form not set to default, specify a value for that form. For example, below example will set "password" to default value and "username", "rememberMe" to "enfometa", true respectively.

forms.reset([
  { name: "username", value: "enfometa" },
  { name: "rememberMe", value: true },
]);
  • reset(values?: ResetConfig[] | null, excludeForms?: ResetConfig | null): void : The last parameter excludeForms specifies which form should be ignored and not reset. For example, below sample code will ignore "rememberMe" to reset and "username" and "password" will be reset to default as first argument is null.
forms.reset(null, [{ name: "rememberMe", value: true }]);

Use with functional component using FormGroup component

import React, { useState } from "react";
import { useEmForms, required, email, EmFormErrorMessage, EmFormGroup, EmFormControl, minLength } from "@enfometa/em-forms";

const LoginWithFormsGroup = (props) => {
  const forms = useEmForms({
    forms: [
      {
        name: "username",
        value: "",
        validators: [
          { name: "required", func: required, message: "Username is required" },
          { name: "email", func: email, message: "Invalid email address" },
        ],
      },
      {
        name: "password",
        value: "",
        validators: [
          { name: "required", func: required, message: "Password is required" },
          { name: "minLength", func: minLength, message: "min Length required is 6", param: { minLength: 6 } },
        ],
      },
      {
        name: "rememberMe",
        value: false,
      },
    ],
  });

  const login = () => {
    if (forms.validate()) {
      const model = forms.toModel();
      //do something with model
      console.log(model);
    }
  };

  const reset = () => {
    //forms.reset();

    //Ignore username reset
    forms.reset(null, [{ name: "username" }]);
  };

  return (
    <div className="container">
      <main>
        <div className="row g-5">
          <div className="col-md-6 col-lg-4">
            <h4 className="mb-3">Functional component Login with FormGroup</h4>
            <div className="row g-3">
              <EmFormGroup emForms={forms}>
                <div className="col-12">
                  <EmFormControl formName="username">
                    <input type="email" className="form-control" placeholder="Email" />
                  </EmFormControl>

                  <div className="error-message">
                    <EmFormErrorMessage formName="username" validatorName="required" />
                    <EmFormErrorMessage formName="username" validatorName="email" />
                  </div>
                </div>
                <div className="col-12">
                  <EmFormControl formName="password">
                    <input type="password" className="form-control" placeholder="password" />
                  </EmFormControl>

                  <div className="error-message">
                    <EmFormErrorMessage formName="password" validatorName="required" />
                    <EmFormErrorMessage formName="password" validatorName="minLength" />
                  </div>
                </div>
                <div className="col-12">
                  <EmFormControl formName="rememberMe">
                    <input type="checkbox" />
                  </EmFormControl>
                </div>
              </EmFormGroup>

              <button className="w-100 btn btn-primary btn-lg" type="button" onClick={login}>
                Login
              </button>
              <button className="w-100 btn btn-primary btn-lg" type="button" onClick={reset}>
                Reset
              </button>
            </div>
          </div>
        </div>
      </main>
    </div>
  );
};

export default LoginWithFormsGroup;

Use with class component using FormGroup component

import React, { useState } from "react";
import { initEmForms, required, email, EmFormErrorMessage, EmFormGroup, EmFormControl } from "@enfometa/em-forms";

class LoginClassComponent extends React.Component {
  constructor(props) {
    super(props);
    //this.state = {};

    this.forms = initEmForms(
      {
        forms: [
          {
            name: "username",
            value: "",
            validators: [
              { name: "required", func: required, message: "Username is required" },
              { name: "email", func: email, message: "Invalid email address" },
            ],
          },
          {
            name: "password",
            value: "",
            validators: [{ name: "required", func: required, message: "Password is required" }],
          },
          {
            name: "rememberMe",
            value: false,
          },
        ],
      },
      this,
      "forms"
    );
  }

  login = () => {
    if (this.forms.validate()) {
      const model = this.forms.toModel();
      console.log(model);
    }
  };

  reset = () => {
    this.forms.reset([{ name: "rememberMe", value: true }]);
  };

  render() {
    return (
      <div className="container">
        <main>
          <div className="row g-5">
            <div className="col-md-6 col-lg-4">
              <h4 className="mb-3">Class component Login with FormGroup</h4>
              <div className="row g-3">
                <EmFormGroup emForms={this.forms}>
                  <div className="col-12">
                    <EmFormControl formName="username">
                      <input type="email" className="form-control" placeholder="Email" />
                    </EmFormControl>

                    <div className="error-message">
                      <EmFormErrorMessage formName="username" validatorName="required" />
                      <EmFormErrorMessage formName="username" validatorName="email" />
                    </div>
                  </div>
                  <div className="col-12">
                    <EmFormControl formName="password">
                      <input type="password" className="form-control" placeholder="password" />
                    </EmFormControl>

                    <div className="error-message">
                      <EmFormErrorMessage formName="password" validatorName="required" />
                    </div>
                  </div>
                  <div className="col-12">
                    <EmFormControl formName="rememberMe">
                      <input type="checkbox" />
                    </EmFormControl>
                  </div>
                </EmFormGroup>

                <button className="w-100 btn btn-primary btn-lg" type="button" onClick={this.login}>
                  Login
                </button>
                <button className="w-100 btn btn-primary btn-lg" type="button" onClick={this.reset}>
                  Reset
                </button>
              </div>
            </div>
          </div>
        </main>
      </div>
    );
  }
}

export default LoginClassComponent;

Profile page sample

This sample demonstrate how to get data from server and set to the em-forms and then update back to the server. This sample also shows a list of errors as well by using method forms.getErrors()

import React, { useState } from "react";
import { useEmForms, required, email, EmFormErrorMessage, EmFormGroup, EmFormControl, range, minLength } from "@enfometa/em-forms";
import RadioGroup from "./base/RadioGroup";

const Profile = (props) => {
  const forms = useEmForms({
    forms: [
      {
        name: "name",
        value: "",
        validators: [
          { name: "required", func: required, message: "Name is required" },
          { name: "minLength", func: minLength, message: "min Length required is 3", param: { minLength: 6 } },
        ],
      },
      {
        name: "email",
        value: "",
        validators: [
          { name: "required", func: required, message: "Email is required" },
          { name: "email", func: email, message: "Invalid email" },
        ],
      },
      {
        name: "age",
        value: 10,
        validators: [
          { name: "required", func: required, message: "Age is required" },
          { name: "range", func: range, message: "Age must be between 18 and 50", param: { min: 18, max: 50 } },
        ],
      },
      {
        name: "gender",
        value: "M",
        validators: [{ name: "required", func: required, message: "Gender is required" }],
      },
      {
        name: "accountType",
        value: "admin",
        validators: [{ name: "required", func: required, message: "Account type is required" }],
      },
    ],
  });

  const accountTypes = [
    { text: "Admin", value: "admin" },
    { text: "User", value: "user" },
    { text: "Visitor", value: "visitor" },
  ];

  //fake http call
  const getProfile = () => {
    return { name: "Enfometa", email: "enfometa@gmial.com", age: 30, gender: "M", accountType: "admin" };
  };

  //fake http call
  const updateProfile = (model) => {
    console.log("Profile updated", model);
  };

  //get values from server and set em-forms object
  useState(() => {
    const profile = getProfile();
    forms.setValuesFromModel(profile);
  }, []);

  const update = () => {
    if (forms.validate()) {
      const model = forms.toModel();
      updateProfile(model);
    }
  };

  const reset = () => {
    forms.reset();
  };

  return (
    <div className="container">
      <main>
        <div className="row g-5">
          <ul className="error-message">
            {forms.getErrors().map((form, indx) => (
              <li key={indx}>{form.message}</li>
            ))}
          </ul>
        </div>
        <div className="row g-5">
          <div className="col-md-6 col-lg-4">
            <h4 className="mb-3">Profile component</h4>
            <div className="row g-3">
              <EmFormGroup emForms={forms}>
                <div className="col-12">
                  <EmFormControl formName="name">
                    <input type="text" className="form-control" />
                  </EmFormControl>

                  <div className="error-message">
                    <EmFormErrorMessage formName="name" validatorName="required" />
                    <EmFormErrorMessage formName="name" validatorName="minLength" />
                  </div>
                </div>
                <div className="col-12">
                  <EmFormControl formName="email">
                    <input type="text" className="form-control" />
                  </EmFormControl>

                  <div className="error-message">
                    <EmFormErrorMessage formName="email" validatorName="required" />
                    <EmFormErrorMessage formName="email" validatorName="email" />
                  </div>
                </div>
                <div className="col-12">
                  <EmFormControl formName="age">
                    <input type="number" className="form-control" />
                  </EmFormControl>

                  <div className="error-message">
                    <EmFormErrorMessage formName="age" validatorName="required" />
                    <EmFormErrorMessage formName="age" validatorName="range" />
                  </div>
                </div>
                <div className="col-12">
                  <EmFormControl formName="gender">
                    <select>
                      <option value="">Please select</option>
                      <option value="M">Male</option>
                      <option value="F">Female</option>
                    </select>
                  </EmFormControl>

                  <div className="error-message">
                    <EmFormErrorMessage formName="gender" validatorName="required" />
                  </div>
                </div>

                <div className="col-12">
                  <EmFormControl formName="accountType">
                    <RadioGroup name={"accountType"} dataSource={accountTypes} />
                  </EmFormControl>

                  <div className="error-message">
                    <EmFormErrorMessage formName="accountType" validatorName="required" />
                  </div>
                </div>
              </EmFormGroup>

              <button className="w-100 btn btn-primary btn-lg" type="button" onClick={update}>
                Update
              </button>
              <button className="w-100 btn btn-primary btn-lg" type="button" onClick={reset}>
                Reset
              </button>
            </div>
          </div>
        </div>
      </main>
    </div>
  );
};

export default Profile;