How does Flutter use policy mode for form validation

In a project, registration, login, modifying user information, placing orders and other functions are implemented without submitting forms. This article explains how to write relatively comfortable form validation code in Flutter.

Suppose we are writing a page to register, and before clicking the register button, we have the following verification logic.

  1. All forms cannot be empty
  2. The mobile phone number contains 11 digits
  3. The mobile phone number must conform to the format
  4. The password must contain at least six characters

If – else mode

We can usually

    if (registerForm.phone.value === ' ') {

            print('Mobile phone number cannot be empty! ')

            return false

    }

    if (registerForm.phone.length < 11) {

        print('Phone number length is 11 digits! ')

        return false

    }

    if(! / ^1(3|5|7|8|9) [09 -] {9}$/.test(registerForm.phoneNumber.value)) {

        print('Mobile number format is not correct! ')

        return false

    }

    if (registerForm.passWord.value === ' ') {

        print('Password cannot be empty! ')

        return false

    }

    if (registerForm.passWord.value.length < 6) {

        print('Password must be at least 6 characters long! ')

        return false

    }

Copy the code

Writing code, can indeed complete the requirements of the business, can complete the form verification, but there are many problems, such as:

  1. The bound function code is quite large and contains a lot of if-else statements, which are disgusting to look at and need to override all the validation rules.
  2. Binding functions are inflexible, and if we add a new validation rule, or want to change the password length from 6 to 8, we have to go deep into the internal implementation of the binding function, which violates the open-closed principle.
  3. The algorithm is not reusable, and if another form is added to the program that requires some similar validation, we are likely to copy the validation logic all over the place.

There are more solutions than problems, and there are solutions, like using strategic patterns to make form validation more elegant and perfect, which I’m going to talk about in a minute. I’m sure a lot of people are resistant to design patterns. Sometimes you already use design patterns in your code and you just don’t know it.

The strategy pattern

There are many ways you can do something, which is called strategy, and its core idea is to separate what to do from who to do it. Therefore, a complete policy pattern should have two classes, one is the policy class, one is the environment class (the main class), the environment class receives the request, but does not process the request, it will delegate the request to the policy class, let the policy class to handle, and the policy class is easy to extend, so that our code is easy to extend.

In the form validation example, the various validation methods form the policy class, such as empty (isNoEmpty), minimum length (minLength), mobile phone number (isMobule), etc. They form the policy class, which provides the environment class to delegate the request.

Write a policy class: A policy class is an object made up of a set of validation methods.



class Strategies {

  // Mandatory

  String require(value, String message) {

    return (value == null || value == ' ' || value == 0)? message :' ';

  }



  // Regex matches

  String pattern(String value, RegExp reg, String message) {

    return reg.hasMatch(value) ? ' ' : message;

  }



  // Minimum length

  String minLength(value, int len, String message) {

    if (value is String) {

      return value.length >= len ? ' ' : message;

    }

    if (value is int || value is double) {

      var _number = value.toDouble();

      return _number >= len ? ' ' : message;

    }

    return message;

  }



  // Maximum length

  String maxLength(value, int len, String message) {

    if (value is String) {

      return value.length <= len ? ' ' : message;

    }

    if (value is int || value is double) {

      var _number = value.toDouble();

      return _number <= len ? ' ' : message;

    }

    return message;

  }

}

Copy the code

Implementation:

// Define the policy class

class Validate extends Strategies {

  var rules;

  var params;

  List<Function> validateList = [];



  Validate(this.rules, this.params) {

    add(rules);

  }



  start() {

    for (var index = 0; index < validateList.length; index++) {

      var message = validateList[index]();

      if(message ! =' ') {

        return validateList[index]();

      }

    }

  }



  void add(rule) {

    var strategies = {

      'require': require,

      'pattern': pattern,

      'minLength': minLength,

      'maxLength': maxLength,

    };

    rule.forEach((keyIndex, ruleValue) {

      var _value = params[keyIndex];

      var _iterator = rules[keyIndex];

      _iterator.forEach((item) {

        item.forEach((key, value) {

          if (strategies.containsKey(key)) {

            if (key == 'require' && value == true) {

              validateList.add(() {

                return strategies[key](_value, item['message']);

              });

            } else {

              validateList.add(() {

                return strategies[key](_value, item[key], item['message']);

              });

            }

          }

        });

      });

    });

  }

}

Copy the code

Use:

class Rules {

  static RegExp isMobile = RegExp(

      r'^((13[0-9])|(14[0-9])|(15[0-9])|(16[0-9])|(17[0-9])|(18[0-9])|(19[0-9]))\d{8}$');

}

void main() {

  var params = {'phone''1234512345123'.'password''213'.'captcha'' '};

  var rules = {

    'phone': [

      {'require'true.'message''Please enter your mobile phone number'},

      {'pattern': Rules.isMobile, 'message''Please enter the correct mobile phone number'},

].

    'password': [

      {'require'true.'message''Please enter your password'},

      {'minLength'6.'message''Password length minimum 6 digits'},

].

    'captcha': [

      {'require'true.'message''Please enter SMS verification code'}

    ]

  };

  var validate = Validate(rules, params);

  var message = validate.start();

  print(message);

}



Copy the code