Tutorial: Form Validation

Form Validation

flitter-forms provides form-template validation and session-based error messages for Flitter. This means that validator schemata are defined for each form, then they are applied to a request submitting information from the corresponding form. That request body is validated using the requirements specified in the form's schema. Any validation errors are written to the session and the user is returned to the form. When the validation completes, the request is passed to the route handler along with the input fields specified in the schema.

Getting Started

We'll take a look at how to create and validate a sample registration form using flitter-forms by defining a validation schema, creating a very basic view, and a handler for it.

Define Validation Schema

Validation schemata contain all fields you wish to access from the form. A validation schema is an Object of key-value pairs where the keys are the names of the fields as they will be submitted and the values are each an Array. Each Array should be a collection of validators that will be applied, in order, to that form.

Let's create a new schema from a template using ./flitter:

./flitter new validator RegistrationForm

This will create the file app/validators/RegistrationForm.validator.js. We will edit it to define the fields in our form and the validator criteria that should be applied to each of those fields:

// RegistrationForm Validator

const RegistrationForm = {

    // field name    validators
    'username':     [ 'required', 'isAlphanumeric' ],
    'password':     [ 'required', 'verify', 'isLength:{"min":8}' ]

}

module.exports = exports = RegistrationForm

flitter-forms makes available a superset of criteria containing those from the validator package. The name of the criterion should be specified as a String. Any arguments that the criterion takes can be specified as a String of valid JSON separated from the criterion name by a : character. More info on available criteria here.

Create the Form View

Now, we'll create a very basic form in the views/register.pug file:

html
    head
        title Register
    body
        for field in form.errors
            for error in field
                p(style='color: red;') Error: #{error}
        form(action='/register' method='POST' enctype='multipart/form-data')
            input(name='username' placeholder='Username' required)
            br
            input(name='password' placeholder='Password' required)
            br
            input(name='password_verify' placeholder='Verify Password' required)
            br
            button(type='submit') Submit

Note that password_verify is required because we specified the verify criterion for the password field.

Define the Routes

Now, we will add routes for our form to app/routing/routers/index.routes.js:

const index = {

    prefix: '/',

    get: {
        '/': [ _flitter.controller('Home').welcome ],
        '/register': [ _flitter.controller('Home').show_registration ]
    },

    post: {
        '/register': [ _flitter.controller('Home').handle_registration ]
    },
}

module.exports = index

Here we specified that the GET request should be handled by the show_registration method on the Home controller, and the POST request should be handled by the handle_registration method on the Home controller.

Handle the Requests

We need to add these methods to the Home controller (app/controllers/Home.controller.js). First, add the show_registration method:

show_registration(req, res){
      // initialize the form in the session
      const form =_flitter.validator('RegistrationForm')
    _flitter.init_form(form, req)

      return _flitter.view(res, 'register', {form: req.session.forms.RegistrationForm})
}

Here, we initialize the form in session. If the form already has data in the session, they will not be destroyed. Then, we render the registration page and pass it the form object as form.

Then, add the handle_registration method (this is just a dummy method):

handle_registration(req, res){
    const validator = _flit.validator('RegistrationForm')

    // Tell the validator to handle the request.
    validator.handle(req, res, '/register', (req, res, input) => {

        // The validation was successful! Let's just look at the input.
        res.send(JSON.stringify(input))
    })
}

Forms makes validators available by name through the _flitter.validator() function, so we get the RegistrationForm validator. Then, we tell the validator to handle the request. If the validation fails, the user will be redirected to the /register route and the error will be displayed. If it is successful, then the callback function will be executed, responding with the input data as JSON to the user (as a demo).