What is Form Validation

In the development mode where the frontend and the backend are independent, the frontend and the backend need to implement their own form validation logic separately. CabloyJS gives full play to the advantages of full stack development. By defining the configuration information of JSON schema, it can support the form validation logic of both frontend and backend. At the same time, it also has the data converting feature. According to the JSON schema configuration information, it automatically converts the form field to the data type required by the backend

The authentication mechanism of CabloyJS uses ajv. We suggest you have a preliminary understanding of ajv

Definition of Validation

Take the form formTest of module test-party as an example:

1. Definition of Schema

Configure JSON Schema of formTest, define form fields: userNamepasswordpasswordAgainsexlanguageavatarrememberMe

The field definition in JSON Schema has two main purposes:

  1. Auto render form at frontend
  2. Verify form data and convert data type at backend

src/module/test-party/backend/src/config/validation/schemas.js

schemas.formTest = {
  type: 'object',
  properties: {
    userName: {
      type: 'string',
      ebType: 'text',
      ebTitle: 'Username',
      notEmpty: true,
      'x-exists': true,
    },
    password: {
      type: 'string',
      ebType: 'text',
      ebTitle: 'Password',
      ebSecure: true,
      notEmpty: true,
      minLength: 6,
    },
    passwordAgain: {
      type: 'string',
      ebType: 'text',
      ebTitle: 'Password again',
      ebSecure: true,
      notEmpty: true,
      const: { $data: '1/password' },
    },
    sex: {
      type: 'number',
      ebType: 'select',
      ebTitle: 'Sex',
      ebMultiple: false,
      ebOptions: [
        { title: 'Male', value: 1 },
        { title: 'Female', value: 2 },
      ],
      ebOptionsBlankAuto: true,
      ebParams: {
        openIn: 'page',
        closeOnSelect: true,
      },
      notEmpty: true,
    },
    language: {
      type: 'string',
      ebType: 'select',
      ebTitle: 'Language',
      ebOptionsUrl: '/a/base/base/locales',
      ebOptionsUrlParams: null,
      ebOptionsBlankAuto: true,
      'x-languages': true,
      notEmpty: true,
    },
    avatar: {
      type: 'string',
      ebType: 'file',
      ebTitle: 'Avatar',
      ebParams: { mode: 1 },
      notEmpty: true,
    },
    rememberMe: {
      type: 'boolean',
      ebType: 'toggle',
      ebTitle: 'Remember me',
    },
  },
};
Name Description
type field type, such as: string/number/boolean
ebType field rendering type, used to indicate the type of frontend rendering component, such as text/toggle/select
ebTitle field title
notEmpty not empty

2. Definition of Validation

src/module/test-party/backend/src/meta.js

validation: {
  validators: {
    formTest: {
      schemas: 'formTest',
    },
  },
  keywords: {
    'x-languages': keywords.languages,
  },
  schemas: {
    formTest: schemas.formTest,
  },
},
Name Description
validation.validators validator list
validation.keywords keyword list
validation.schemas schema list

The relationship between validator and schema

  • One validator can correspond to multiple schemas, but in general, only one schema is required

Validation at Backend

Module a-validation provides two validation middleware: validate and validation

1. validate

Middleware validate automatically performs validation and converting logic of form data according to middleware parameters configured in API route

src/module/test-party/backend/src/routes.js

{ method: 'post', path: 'kitchen-sink/form-schema-validation/saveValidation', controller: testKitchensinkFormSchemaValidation, middlewares: 'validate',
  meta: {
    validate: { validator: 'formTest' },
  },
},
名称 说明
middlewares: ‘validate’ Because validate is a local middleware, it needs to be explicitly declared
meta.validate middleware parameters
meta.validate.module validator module name
meta.validate.validator validator name

2. validation

The global middleware validation injects object validation into ctx.meta, which is convenient for validation by code

a-authsimple/backend/src/config/passport/auth.js

// validate
await ctx.meta.validation.validate({
  module: 'a-authsimple', validator: 'signin', data: body 
});
Name Description
module module name
validator validator name
data form data to be validated

Rendering at Frontend

Module a-components provides a global Vue component eb-validate, which has two main purposes:

  1. Render Form
  2. Intercept and display the validation error information returned by the backend

1. Auto Render

The form is automatically rendered by eb-validate according to the schema information provided by validator

src/module/test-party/front/src/kitchen-sink/pages/form-schema-validation/formSchemaAuto.vue

<eb-validate v-if="item" ref="validate" auto :data="item" :params="validateParams" :onPerform="onPerformValidate" @submit.prevent="onFormSubmit">
</eb-validate>
Name Description
auto true: auto render, false: custom render
data form data
params parameters
params.module validator module name
params.validator validator name
onPerform perform backend API route here
submit.prevent respond to submit event
  1. When clicking the button Save or responding to the 'Submitevent, invoke the methodperformofeb-validate, thus triggering theonPerformofeb-validate`
  2. Invoke the backend API route in onPerform. If there are validation errors, they will be displayed automatically

2. Custom Render

Customize the layout of form components within eb-validate, which can be more targeted and flexible

src/module/test-party/front/src/kitchen-sink/pages/form-schema-validation/formSchemaCustom.vue

<eb-validate v-if="item" ref="validate" :auto="false" :data="item" :params="validateParams" :onPerform="onPerformValidate">
  <eb-list form no-hairlines-md @submit.prevent="onFormSubmit">
    <eb-list-item-validate dataKey="userName"></eb-list-item-validate>
    <eb-list-item-validate dataKey="password"></eb-list-item-validate>
    <eb-list-item-validate dataKey="passwordAgain"></eb-list-item-validate>
    <eb-list-item-validate dataKey="sex"></eb-list-item-validate>
    <eb-list-item-validate dataKey="language"></eb-list-item-validate>
    <eb-list-item-validate dataKey="avatar"></eb-list-item-validate>
    <f7-list-item v-if="item.avatar">
      <img class="avatar avatar48" :src="getAvatarUrl(item.avatar,48)">
    </f7-list-item>
    <eb-list-item-validate dataKey="rememberMe"></eb-list-item-validate>
  </eb-list>
</eb-validate>