0.1.0 • Published 5 years ago

react-shield-form v0.1.0

Weekly downloads
1
License
MIT
Repository
-
Last release
5 years ago

React Shield Form

A form library that shields you from all the nasty stuff, when dealing with forms.

Hail Brethern, and....Sistren! Ahh Forms, something we all hate dealing with, instead of focusing on our Mission, we have to deal with all kinds of issues when it comes to forms, even for the most simplest tasks.

Spend more time drinking ale! and less time battling state management and validations!

react-shield-form keeps track of state, errors and handles validations (some basic validations are provided baked in, though you're free to use your own), you can let the library handle alot of this for you, though for more specific edge cases, various API's are exposed to allow you to use the library as you need.

Installation

Using your favourite package manager cough yarn cough.

NPM

npm install react-shield-form

YARN

yarn add react-shield-form

NOTE

  • There are no dependencies required though, currently you do need to be able to use async / await this may change in the near future and I will remove this constraint.
  • react-shield-form relies on the new context-api so you would need to use React v16+

Validations

react-shield-form comes with various validations baked in, to cover most of your general needs. The validations prop expects an array to be passed with strings from the selection below.

Default Validations

Currently these are the following validations which are included in react-shield-form

  • "required": This field must have a value inside
  • "min:number": The minimum required characters in the field E.g. "min:3"
  • "max:number": The maximum characters allowed in a field E.g. "max:15"
  • "numbers": Only numeric characters
  • "email": (OWASP Regex) Email Validation
  • "safe-text": (OWASP Regex) Lower and upper case letters and all digits
  • "credit-card": (OWASP Regex) Valid Credit / Debit Card no.
  • "valid-ip": (OWASP Regex) Valid IP No Validation
  • "simple-password": (OWASP Regex) 4 to 8 character password requiring numbers and both lowercase and uppercase letters
  • "complex-password": (OWASP Regex) 4 to 32 character password requiring at least 3 out 4 (uppercase and lowercase letters, numbers and special characters) and no more than 2 equal characters in a row

MORE TO COME

Custom Validations

You can pass in an object inside of the array to provide your own rules for validations also such as the example below. What errMsg is the error which will be displayed if the validation requirements are not met

Sync Custom Validation

const validations = [
  {
    errMsg: "You must have more than 2 characters!"
    validate: input => input.length < 2
  }
]

Async Custom Validation

Async validations are also handled, if you want to check on the server for specific cases. You must add the async flag, and the validate function must then return a promise.

const validations = [
  "required",
  {
    async: true,
    errMsg: "This field should not include the string javascript!"
    validate: input => fakeApiCall(input)
  }
]

const fakeApiCall = input => {
  return new Promise((resolve) => {
    setTimeout(() => {
      if (input.includes("javascript")) {
        resolve();
      }
    }, 500);
  });
};

Simple Form Example

The examples below are not opinionated, the Feedback component, does not need to be placed within the same Group component. You are free to add in your own components, images etc inside of the form, to style it to your needs.

Note

  • The ID is Required in your Input components
  • The ID for the feedback must match the ID of the Input for validation feedback
  • The Feedback component with ID of "server" will display global messages
import { Form, Label, Input, Feedback, Submit, Group } from "react-shield-form";

<Form onSubmit={onSubmit} async>
  <Group>
    <Label>Name:</Label>
    <Input type="text" id="name" validations={["required"]} validateOnChange />
    <Feedback id="name" />
  </Group>
  <Group>
    <Button type="submit">Submit</Button>
  </Group>
  <Feedback id="server" />
</Form>

// MOCK API Call
function onSubmit(values) {
  const testCase = true;
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (testCase) {
        // Message to be displayed on success of form submit
        resolve("Form has been submitted!");
      } else {
        // Message to be displayed if error returned from server
        reject("Oh no there has been a server error!");
      }
    }, 500);
  });
}

Advanced Form Example

The library is compatible with any CSS Framework, in the example below Bootstrap CSS classnames are being used

Note

  • errorClass: This is the class that will be appended when a validation error is raised to style the feedback how you like
  • validateOnChange: This will run the validations on each key change in real time.
const validations = [
  "required",
  {
    async: true,
    errMsg: "This field should not include the string javascript!"
    validate: input => fakeApiCall(input)
  }
]

const fakeApiCall = input => {
  return new Promise((resolve) => {
    setTimeout(() => {
      if (input.includes("javascript")) {
        resolve();
      }
    }, 500);
  });
};

<Form
  onError={this.onError}
  onChange={this.onChange}
  onSubmit={this.onSubmit}
  async
>
  <Group className="form-group">
    <Label>Name</Label>
    <Input
      type="text"
      id="name"
      className="form-control"
      errorClass="input-error"
      validations={validations}
      validateOnChange
    />
    <Feedback id="name" errorClass="feedback-error" />
  </Group>
  <Group className="form-check">
    <Input
      id="agree"
      type="checkbox"
      className="form-check-input"
      validateOnChange
      validations={["required"]}
    />
    <Label className="form-check-label">
      Agree to terms and conditions
    </Label>
    <Feedback id="agree" errorClass="feedback-error" />
  </Group>
  <Group
    className="d-flex justify-content-between">
    <Button className="btn btn-primary" type="submit">
      Submit
    </Button>
  </Group>
  <Feedback
    id="server"
    errorClass="feedback-error"
    successClass="feedback-success"
  />
</Form>


onChange = (state, target) => {
  // The whole form state on each change
  // The target is provided also, so you know which form element was changed
};

onError = (form, server) => {
// Array of all form validation errors
// The server error thrown
};


// MOCK API Call
onSubmit = async values => await AuthSignIn(values);

const AuthSignIn = () => {
  const testCase = true;
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (testCase) {
        resolve("Form Submitted!");
      } else {
        reject("There has been a server error!");
      }
    }, 500);
  });
};

Form handle loadinging

The form can manage loading state for you when it is in submission, below is an example of how the group with the Submit button should be used.

  • Pass in the handleLoading prop
  • You also need to pass in a component which will be rendered while loading
  <Group
    handleLoading
    loader={<YourCustomLoader />}
    className="d-flex justify-content-between">
    <Button className="btn btn-primary" type="submit">
      Submit
    </Button>
  </Group>

Password Validation Example

The form is handled as the examples above, below will show how you can manage password validation

  • The validate function also exposes a 2nd argument, which is all the forms state values
  • You can use this to compare different fields to do things such as checking both password fields match
  • If Input type is password it will allow you to pass a component in the icon prop
const checkPassword = [
  {
    errMsg: "Do not match!",
    validate: (input, values) => {
      if (input !== values["password"]) return false;
      return true;
    }
  }
];

<Group className="form-group">
  <Label>Password</Label>
  <Input
    type="password"
    icon={
      <img
        className="icon-image"
        height="25"
        src="http://www.iconarchive.com/download/i99461/webalys/kameleon.pics/Key.ico"
      />
    }
    id="password"
    className="form-control"
    successClass="input-success"
    errorClass="input-error"
    validations={["simple-password"].concat(checkPassword)}
    validateOnChange
  />
  <Feedback
    id="password"
    successClass="feedback-success"
    errorClass="feedback-error"
  />
</Group>
<Group className="form-group">
  <Label>Confirm Password</Label>
  <Input
    type="password"
    icon={
      <img
        height="25"
        src="http://www.iconarchive.com/download/i99461/webalys/kameleon.pics/Key.ico"
      />
    }
    id="confirm-password"
    className="form-control"
    successClass="input-success"
    errorClass="input-error"
    validations={checkPassword}
    validateOnChange
  />
  <Feedback
    id="confirm-password"
    successClass="feedback-success"
    errorClass="feedback-error"
  />
</Group>

Component API

Input

The input component can take the following props:

  • id: This is for the library to identify the component REQUIRED - String
  • type: "text" | "number" | "textarea" REQUIRED - String
  • className: The customize the component how you like
  • style: For inline styling as you would a normal react js component
  • errorClass: The CSS to be appended to the input when a validation error occurs E.g. Red border around input
  • successClass: The CSS to be appended to the input when a validation requirements are met E.g. Green border around input
  • validations: The expects an Array of either strings or objects (See validations)
  • validateOnChange: This is to trigger the fields validation check while typing
  • validateOnBlur: This is to trigger the fields validation check on Blur
  • icon: When type="password" you can pass in a component for your icon to trigger the input to show either password or text

Feedback

  • id: This is for the library to identify the component - This must match a current Input you have named in the form REQUIRED - String
  • className: The customize the component how you like
  • errorClass: The CSS to be appended to the input when a validation error occurs E.g. Make the text green (This will be useful when successClass is implemented)
  • successClass: The CSS to be appended to the input when a validation requirements are met E.g. Green text success message
  • successMsg: The message to display when validation requirements are met

Group

  • className: The customize the component how you like
  • handleLoader: Set this prop if you want the form to handle form loading on form submission
  • loader: Pass in a component to render while form is submitting form

Button

PROPS

  • id: "reset" | None OPTIONAL
    • "reset": Button will reset form state to originail initialization state
  • type: "submit" | None OPTIONAL
    • "submit": Button will act as a normal submit button

Todo

  • Handle Select Inputs
  • Handle Radio Buttons
  • Handle success validation on fields

Future Roadmap

  • Handle 3rd Party Form Elements
0.1.0

5 years ago

0.0.3

5 years ago

0.0.1

5 years ago