1.0.0-rc.2 • Published 1 year ago

@wasable/react-form v1.0.0-rc.2

Weekly downloads
-
License
ISC
Repository
-
Last release
1 year ago

Form Usage

To use an HOC form with innerState, errors handlings and validation, an helper is available like as follows:

import { classicForm } from "@wasable/react-form";

you need to provide it some required properties:

initialData : is the item to edit OR the initialData in a create Action
actionForm : is the action triggered on submit, if the validation is correct

you can also provide it with an optional property:

load : a function that is triggered in the constructor of the form
returnCompleteData : if set to true, the first parameter of the actionform function will be the full formdata, not only the modified one
onSubmitError : function triggered when submit is triggered but the validation is NOK (WARNING: this is not triggered on API error ATM)

finally, an example:

import { connect } from "react-redux";
import { classicForm } from "@wasable/react-form";

// Your components to wrap
import ExampleComponent from "path/to/component";

const mapStateToProps = (state) => {
  initialData: {
  } // here you store your selector or your initialData file
  returnCompleteData: false;
};

const mapDispatchToProps = () => {
  return {
    actionForm: (data) => {
      // data: is either the full data of the form or only the modified data
      // here is the main action of your form, usually an Api call for creation/update
    },
    onSubmitError: (errorList) => {
      // errorList : an array of all the text errors in your form
      // you can dispatch here an action to display a toaster, for example.
    },
    load: () => {
      // you can dispatch here an action to retrieve necessary data for your form, such as civilityList, cityList... etc.
    },
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(classicForm(ExampleComponent));
import { HOCErrorLabel } from "@wasable/react-form";
import ComponentLabel from "./some_path_to_component";

// Utils
import { fieldDefaultPropTypes } from "./const/propTypes";
import { fieldDefaultProps } from "./const/defaultProps";

export default class ExampleComponent extends Component {
  constructor(props) {
    super(props);
    props.setValidator(/* some rules, some custom rules func */);
  }

  render() {
    const ErrorMessage = HOCErrorLabel(ComponentLabel);

    const { getValidationStatus, handleChange, formData, submit } = this.props;

    const { property_name, second_property_name } = formData;

    return (
      <>
        <div>
          <div>
            <span>Some Label</span>
            <Input
              // some props...
              value={property_name}
              onChange={(e) => handleChange("property_name", e.value)}
            />
            <ErrorMessage
              getKeysStatus={() =>
                getValidationStatus(["some_rule_name", "some_rule_name_again"])
              }
              isMulti={true}
            />
          </div>
          <div>
            <span>Some Label Again</span>
            <Input
              // some props...
              value={second_property_name}
              onChange={(e) => handleChange("second_property_name", e.value)}
            />
            <ErrorMessage
              getKeysStatus={() =>
                getValidationStatus([
                  "some_rule_name",
                  "some_rule_name_again",
                  "some_rule_name_the_prequel",
                ])
              }
              isMulti={false}
            />
          </div>
        </div>
        /* will triger the validation according to rule set in constructor after
        that, will triger actionForm (if validation OK) or (onSubmitError) */
        <button onClick={submit}>Valider</button>
      </>
    );
  }
}

Validation

Validator

The validator is a javascript class who can handle rules and validate a javascript object accordingly

Example

import { Validator } from "@wasable/beable-form";

// some code
const rules = {
  my_strict_rules_name: {
    // the key corresponding to a given rules (default or custom)
    rule: "stricktlySameValue",
    // the property of the object to Test given to the ruleFunction in the order
    fields: ["bar", "foo"],
    // error message given if invalid
    message: "you striclty f***** something, mate !",
  },

  my_rules_name: {
    // the key corresponding to a given rules (default or custom)
    rule: "sameValue",
    // the property of the object to Test given to the ruleFunction in the order
    fields: ["foo", "bar"],
    // error message given if invalid
    message: "you f***** something, mate !",
  },
};

const rulesFunc = {
  // here we are defining a custom rules (for defaut rules given see Rules -> Native Rules
  stricktlySameValue: isStrictlySameValue,
  sameValue: isSameValue,
};

// here is the definition of the function to use in our custom rules
// note that in this exemple props1 = objectToTest.bar's value and props2 = objectToTest.foo's value
function isStrictlySameValue(props1, props2) {
  return props1 === props2;
}

// here is the definition of the function to use in our custom rules
// note that in this exemple props1 = objectToTest.foo's value and props2 = objectToTest.bar's value
function isSameValue(props1, props2) {
  return props1 == props2;
}

// create our validator with our rules and custome validation function
const exampleValidator = new Validator(rules, rulesFunc);

// --- validate Zone ---
// firstTest will be : { my_strict_rules_name: true, my_rules_name: true }
const firstTest = exampleValidator.validate({
  foo: "1",
  bar: "2",
});

// secondTest will be : { my_strict_rules_name: true }
const secondTest = exampleValidator.validate({
  foo: "1",
  bar: 1,
});

// thindTest will be : {}  because all rules are valid
const thirdTest = exampleValidator.validate({
  foo: "1",
  bar: "1",
});

// --- hasError Zone ---

// will return true
exampleValidator.hasError(
  ["my_strict_rules_name", "my_rules_name"],
  secondTest
);

// will return true
exampleValidator.hasError(["my_strict_rules_name"], secondTest);

// will return false
exampleValidator.hasError(["my_rules_name"], secondTest);

// --- getStatus Zone ---
// ---- firstTest Zone ----

// will be : ['you striclty f***** something, mate !', 'you f***** something, mate !']
exampleValidator.getStatus(
  ["my_strict_rules_name", "my_rules_name"],
  firstTest
);

// will be : ['you striclty f***** something, mate !']
exampleValidator.getStatus(["my_strict_rules_name"], firstTest);

// will be : ['you f***** something, mate !']
exampleValidator.getStatus(["my_rules_name"], firstTest);

// will be : []
exampleValidator.getStatus(["another_rule_name"], firstTest);

// ---- secondTest Zone ----

// will be : ['you striclty f***** something, mate !']
exampleValidator.getStatus(
  ["my_strict_rules_name", "my_rules_name"],
  secondTest
);

// will be : ['you striclty f***** something, mate !']
exampleValidator.getStatus(["my_strict_rules_name"], secondTest);

// errorMessages will be : []
exampleValidator.getStatus(["my_rules_name"], secondTest);

// ---- thirdTest Zone ----

// will be : []
exampleValidator.getStatus(
  ["my_strict_rules_name", "my_rules_name"],
  thirdTest
);

// will be : []
exampleValidator.getStatus(["my_strict_rules_name"], thirdTest);

// will be : []
exampleValidator.getStatus(["my_rules_name"], thirdTest);

// some code

Rules

Syntaxe

const rulesList = {
  my_rules_name_1: {
    // the key corresponding to a given rules (default or custom)
    rule: "someRule",
    // the property of the object to Test given to the ruleFunction in the order
    fields: ["props1", "props2", "propsX"],
    // error message given if invalid
    message: "a message",
  },
  my_rules_name_X: {
    rule: "someRule",
    fields: ["props7", "propsX"],
    message: "a message",
  },
};

Native Rules

email : The field under validation must be formatted as an e-mail address
siret : The field under validation must be a FRENCH siret number
phone : The field under validation must be a FRENCH phone number (ten numeric)
password : The field under validation casted in string must contain uppercase, lowercase, number and at least eight character
required : The field under validation musn't be null, undefined or empty string
isSame : The fields under validation must be strictly identical (===)
password_repeat : same as previous, here for backward compatibility
isTrue : The field under validation must be true
isFalse : The field under validation must be true

Helpers

Generators

To ease the writing of rules, some helpers (called 'rulesGenerators') are available:

generateRequiredRules

Description
will return an object containing required rules for multiple properties in your form

Syntaxe

generateRequiredRules(fields, message);

Parameters

fields: Arraystring -> contain all the properties which required rule will be generated
message: string -> an error message (CAUTION: this will be applied to all the rule generated in this manner), if not specified this will return '${property_name}.required'

Return value

a Javascript object with pair key/value -> ruleName/ruleValue (formatted defined in 'RULES')

import { generateRequiredRules } from "@wasable/beable-form";

// some code

const exampleRulesJSON = generateRequiredRules([
  "my_property_1",
  "my_property_2",
  /*... */ "my_property_X",
]);

// some code

HOCErrorLabel

Will give to the wrapped component an array of error message depending on the rules to watch

Property Needed: getKeysStatus : a function who will return the list of message to handle (usually the return of getValidationStatus from the validationHOC) isMulti : if multiple message can be returned at once

Property given to Wrapped Component: errorToDisplay : an array of message to display

import { HOCErrorLabel } from "@wasable/react-form";
import ComponentLabel from "./some_path_to_component";

// Utils
import { fieldDefaultPropTypes } from "./const/propTypes";
import { fieldDefaultProps } from "./const/defaultProps";

export const TextField = (props) => {
  const ErrorMessage = HOCErrorLabel(ComponentLabel);

  const { getValidationStatus } = props;

  return (
    <div>
      <ErrorMessage
        getKeysStatus={() => getValidationStatus(validationErrors)}
        isMulti={true}
      />
    </div>
  );
};

In this exemple, the component 'ComponentLabel', will receive an array of string (who are the corresponding message of all the rules 'watched')