JS rewrites form validation using policy mode

Posted by stevenm on Sat, 29 Jan 2022 20:12:57 +0100

Original verification

Now we have a form:

<form action="/" id="myForm" method="POST">
    user name:<input name='user' type="text"> 
    password:<input name='pwd' type="text"> 
    <button type="submit" name='btn'>Submit Form </button>
</form>

We need to do form verification, so the common writing method is the following if # else branch processing

<script>
    var form = document.getElementById('myForm');
    form.btn.onclick = function(e) {
        var userVal = form.user.value;
        var pwdVal = form.pwd.value;

        if (!userVal) {
            console.log('User name cannot be empty');
            return false;
        }

        if (!pwdVal || (pwdVal.length <= 6)) {
            console.log('The password length must be greater than 6 digits');
            return false;
        }

        console.log('Submitted successfully');
        return false;
    }
</script>

But this way of writing has a big disadvantage, that is, it does not have scalability. If you want to verify one more mobile phone number, you need to add another else branch for business processing. And the written verification can not be applied to other forms, which is very inconvenient.

Use policy mode validation

In order to realize dynamic authentication and improve code extensibility, we can use policy mode to rewrite form verification

Step 1: define policy object

//Policy object
    var strategy = {
        require: function(val, msg) {
            if (!val) {
                return msg
            }
        },
        min: function(val, length, msg) {
            if (!val || (val.length <= 6)) {
                return msg
            }
        },
        phone: function(val, msg) {
            let patt = /^1[3-9]\d{9}$/
            let flag = patt.test(val)
            if (!flag) {
                return msg
            }
        }
    }

The purpose of defining policy objects is to abstract and encapsulate the business logic of each verification algorithm. Each addition of a verification is actually a new policy. You can directly add a new method to the policy object to facilitate expansion. Abstraction is to make the method adapt to more application scenarios. For example, the length in the min method can specify characters of any length.

Part II: defining policy classes

//Policy class
    var Validate = function() {
        this.rules = []

        this.add = function(dom, rule, msg) {
            let args = rule.split(':')
            let func = args.shift();
            args.push(msg)
            args.unshift(dom.value)

            let obj = {
                func,
                args
            }
            this.rules.push(obj)
                //strategy[func]
        }

        this.check = function() {
            var errors = []
            for (var i = 0; i < this.rules.length; i++) {
                var error = strategy[this.rules[i].func].apply(strategy, this.rules[i].args) //Call the method in the policy object
                if (error) {
                    errors.push(error)
                }
            }
            return errors
        }
    }

We define a rule attribute, an add method and a check method. The rules attribute records the verification rules added in the add method. The check method circularly calls the verification rules in the rules to the methods in the policy object. This enables high availability of policy objects.

call

    function checkForm() {
        var validate = new Validate()
        validate.add(form.user, 'require', 'User name must be filled in')
        validate.add(form.pwd, 'min:6', 'Password length must be greater than 6 digits')
        var res = validate.check()

        if (res.length) {
            console.log(res)
        } else {
            console.log('Verification successful')
        }

        return false;
    }
    var form = document.getElementById('myForm')
    form.btn.onclick = checkForm

It can be seen that after using the policy mode, calling validation becomes very simple. It can also be used for other files, which can be encapsulated into a class library for use.

Full code:

    //Policy object
    var strategy = {
        require: function(val, msg) {
            if (!val) {
                return msg
            }
        },
        min: function(val, length, msg) {
            if (!val || (val.length <= 6)) {
                return msg
            }
        },
        
    }

    //Policy class
    var Validate = function() {
        this.rules = []

        this.add = function(dom, rule, msg) {
            let args = rule.split(':')
            let func = args.shift();
            args.push(msg)
            args.unshift(dom.value)

            let obj = {
                func,
                args
            }
            this.rules.push(obj)
                //strategy[func]
        }

        this.check = function() {
            var errors = []
            for (var i = 0; i < this.rules.length; i++) {
                var error = strategy[this.rules[i].func].apply(strategy, this.rules[i].args) //Call the method in the policy object
                if (error) {
                    errors.push(error)
                }
            }
            return errors
        }
    }
    //call
    function checkForm() {
        var validate = new Validate()
        validate.add(form.user, 'require', 'User name must be filled in')
        validate.add(form.pwd, 'min:6', 'The password length must be greater than 6 digits')
        var res = validate.check()

        if (res.length) {
            console.log(res)
        } else {
            console.log('Verification successful')
        }

        return false;
    }
    var form = document.getElementById('myForm')
    form.btn.onclick = checkForm

Let's look at scalability. If we want to add one more mobile phone number, we only need to add the corresponding method in the policy object:

Run successfully.

You can see that the rewritten code has good scalability and is more simple and convenient to use.

summary

In some scenarios where there are many branches and business logic needs frequent if else judgment, the abstract encapsulation strategy mode can be considered to complete the work task, making the code easier to expand and more applicable

 

 

 

Topics: Front-end