Simple and lightweight way to validate javascript object using max-validator
Tags: javascript, react, node, tutorial
Published: 2020-05-22 07:09:38

---
title: Simple and lightweight way to validate javascript object using max-validator
published: true
description: Latest update made it more flexible and usable
tags: javascript, react, node, tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/irwzxe1f38ee8a76x7et.png
---

Hello, I hope you have seen my first article about **[max-validator](https://github.com/malkhazidartsmelidze/max-validator)** where I talk about this library and the way to use it.

Today I released `max-validator`'s update and it became more flexible and compatible for almost every requirement. :smiling_face_with_three_hearts:

---

First of all lets talk about how install and use **[max-validator](https://www.npmjs.com/package/max-validator)** and then I'll introduce you to updates.

Installation is like every other npm package:
```bash
npm i max-validator --save
# or
npm install max-validator --save 
# or using yarn
yarn add max-validator
```

Then you can use it with only one method call:
```javascript
import V from 'max-validator';
V.validate(data, validationScheme);
```
Where `data` is simple javascript object containing data to validate and `validationScheme` is object where keys are `data` keys and values are scheme rules.

Let's see example how we can validate user registration form:
```javascript
var validationScheme = {
  name: 'required|min:3|max:50|alpha',
  lastname: 'required|min:3|max:50|alpha',
  email: 'required|email|ends_with:gmail.com',
  birthdate: 'required|date',
  address: 'required|string|max:100|contains_one:st,str,ave,avenue,#',
  password: 'required|min:6|alpha_num',
  age: 'required|between:18,70|number'
};

var result = V.validate({
  name: 'Malkhazi', 
  lastname: 'Dartsmelidze', 
  email: 'examplemail@gmail.com',
  birthdate: '1997-17-07',
  age: 22,
  address: 'Rustaveli Avenue #333',
  password: '12345678',
  password_confirm: '12345678',
}, validationScheme);
```

I thought it already was very simple and compact but I realized that I was wrong then I decided to add new features to it and make it very flexible, usable and full validation library, so I did it.


First see minor changes:
In version `max-validator@1.1.0` I added and changed a few validation rules:
- contains_one
- contains_all
- numeric
- alpha_numeric

And now lets talk about **Major Changes**:

**You can pass array of rules in Validation scheme:**
```javascript
V.validate(data, {
  name: ['required', 'min:3', 'max:50', 'alpha'],
  email: ['required', 'email', 'ends_with:gmail.com'],
});
```

**You can pass object of rules in Validation scheme:**
```javascript
V.validate(data, {
  name: {
    required: true,
    min: 3,
    max: 50,
    alpha: true
  },
  email: {
    required: true,
    email: true,
    max: 50,
    ends_with: 'gmail.com'
  }
});
```
In this way rules are more readable, :monocle_face: flexible and it has major advantage - **Conditional Rules**:
```javascript
V.validate(data, {
  name: ['required', 'min:3', 'max:50', canWriteNickname ? 'alpha_numeric' : 'alpha'],
  email: ['required', 'email', requiredGmailEmail ? 'ends_with:gmail.com' : ''],
});
```

---

In `max-validator@1.0` we couldn't validate whether email or nickname was unique or address was correct address or not, 

But now you can do it with inline or predefined validation functions.
Lets see how it works:

```javascript
function checkIfEmailIsUnique(value){
  var response = checkEmail(value)
  if(response.isUnique) {
    return true;
  }

  return 'Sorry, this email is already used';
}

V.validate(data, {
  name: ['required', 'min:3', 'max:50', canWriteNickname ? 'alpha_numeric' : 'alpha'],
  email: ['required', 'email', requiredGmailEmail ? 'ends_with:gmail.com' : '', checkIfEmailIsUnique, function(value){
    /* You can pass as many inline functions as you want */
    return 'Just return true if value is valid or return string if you want to get error';
  }],
  nickname: {
    required: true,
    alpha_numeric: true,
    max: 50,
    checkNickname: function(value){
      var response = checkEmail(value)
      if(response.isUnique) {
        return true;
      }

      return 'Nickname not aviable';
    }
  }
});
```

Pretty interesting, huh? :heart_eyes:

But what about password confirmation, which is very important input for registration form? :roll_eyes: Or what about whether age is correct relative to birthdate? :roll_eyes:
`max-validator@1.1.0` - Challenge accepted :sunglasses:

Simply pass second argument in function and you get entire validation data:
```javascript
var result = V.validate({
  name: 'Malkhazi', 
  lastname: 'Dartsmelidze', 
  email: 'examplemail@gmail.com',
  birthdate: '1997-17-07',
  age: 22,
  address: 'Rustaveli Avenue #333',
  password: '12345678',
  password_confirm: '12345678',
}, {
  ...
  password: 'required|min:6|alpha_numeric',
  password_confirm: [
    function(value, data){
      if(value === data.password) return true;

      return 'Passwords didn\'t match'
    }
  ],
  age: {
    required: true,
    between: [18, 70],
    validateIfCorrect: function(value, data){
      if(value != moment().diff(moment(value.date, 'YYYY-MM-DD'), 'years')) {
        return 'Age or birthdate is incorrect';
      }
      return true;
    }
  }
});
```

**[max-validator](https://github.com/malkhazidartsmelidze/max-validator)** is not even 2.5KB in size which is extremly important in front-end applications.

My next major goals is to integrate it with other libraries like: **Formik**, **react-hook-form** and others.
> Note: **Formik** validator `Yup` is 30KB and **react-hook-form**'s validator `joi` is 41KB

Oh, I almost forgot to write how to use `max-validator` with React.js.

Before that, lets learn how to get errors:
```javascript
var result = Validator.validate(data, validationScheme);

// Get if validate returned error
result.hasError; // Boolean

// Get errors object
result.errors; // Object

// Get if given field has error
result.isError('name'); // Boolean

// Get if given field has error of given validation rule
result.isError('name', 'max'); // Boolean
result.isError('name', 'myCustomFunctionNamePassedInArrayOrObject'); // Boolean
// Note: you cant get whether inline function passed validation or not

// Get first validation error message of field
result.getError('name'); // String

// Get all validation error messages of field
result.getError('name', true); // String (joined messages with comma)
```

Now use it in React.js:
```javascript
import React from 'react';
import V from 'max-validate';

const LoginForm = (props) => {
  const [formState, setFormState] = React.useState({
    isValid: false,
    values: {},
    touched: {},
    errors: V.empty(),
  });

  useEffect(() => {
    const result = V.validate(formState.values, {
      email: 'required|email',
      password: 'required|min:6'
    });

    setFormState((formState) => ({...formState,
      isValid: result.hasError,
      errors: result.hasError ? result : V.empty(),
    }));
  }, [formState.values]);

  const handleChange = (event) => {
    event.preventDefault();

    setFormState((formState) => ({ ...formState,
      values: { ...formState.values,
        [event.target.name]: event.target.value,
      },
      touched: {...formState.touched,
        [event.target.name]: true,
      },
    }));
  };

  const hasError =  (field) => (formState.touched[field] && formState.errors.isError(field));

  return (
    <form>
      <input hasError={hasError('email')} name="email" onChange={handleChange} />
      <input hasError={hasError('password')} name="password" onChange={handleChange} />
      <button disabled={!formState.isValid}>Login</button>
    </form>
  );
}
```

Thank you for reading this article, I hope you liked it. 
If so, please **Share** this article **Star** and **Watch** **[Guthub Repository](https://github.com/malkhazidartsmelidze/max-validator)** to get notifications about changes and realeases, this helps me sooooo much.