본문 바로가기
Study Note/Javascript

javascript #디자인패턴 - 폼 검증을 위한 데커레이터 패턴(decorator pattern)

by 시뮝 2021. 2. 10.
728x90

데커레이터 패턴

프락시 패턴은 호출되는 객체가 아닌 별도의 중간자 역할을 수행하는 프락시 객체가 추가 기능을 수행하는 패턴이라고 한다면, 데커레이터(decorator) 패턴은 호출 대상이 되는 객체에 추가 기능들을 자유롭게 추가하는 패턴입니다.

 

데커레이터 패턴을 유용하게 이용할 수 있는 곳은 바로 검증 도구입니다.

 

구현 (폼 검증을 위한 데커레이터 패턴 실용 예)

<html>
    <head>
    </head>
    <body>
        <form id="personalInformation">
            <label>First name: <input type="text" class="validate" data-validate-rules="required alphabet" name="firstName"/></label>
            <br/>
            <label>Last name: <input type="text" class="validate" data-validate-rules="required alphabet" name="lastName"/></label>
            <br/>
            <label>Age: <input type="text" class="validate" data-validate-rules="number" name="age"/></label>
            <br/>
            <label>Gender: <select class="validate" data-validate-rules="required">
                <option>Male</option>
                <option>Female</option>
            </select></label>
            <br/>
            <input type="submit"/>
        </form>
        
        <script type="application/javascript">
        (function(){
            let formPersonalInformation = document.getElementById("personalInformation"), 
                validator = new Validator(formPersonalInformation);
            
            function Validator(form) {
                this.validatingForm = form;
                form.addEventListener("submit", function() {
                    if (!validator.validate(this)) {
                        event.preventDefault();
                        event.returnValue = false;
                        console.log("Fail to validate");
                        return false;
                    }
                    event.preventDefault();
                    event.returnValue = false;
                    console.log("Success to validate");
                    return true;
                });
            }
            Validator.prototype.ruleSet = {};
            Validator.prototype.decorate = function (ruleName, ruleFunction) {
                this.ruleSet[ruleName] = ruleFunction;
            }
            Validator.prototype.validate = function (form) {
                let validatingForm = form || this.validatingForm,
                    inputs = validatingForm.getElementsByClassName("validate"),
                    length = inputs.length,
                    i, j,
                    input,
                    checkRules,
                    rule,
                    ruleLength;
                
                for(i = 0; i < length; i++) {
                    input = inputs[i];
                    if (input.dataset.validateRules.split(" ")) {
                        checkRules = input.dataset.validateRules.split(" ");
                        ruleLength = checkRules.length;
                        
                        for (j = 0; j<ruleLength; j++) {
                            rule = checkRules[j];
                            if (this.ruleSet.hasOwnProperty(rule)) {
                                if (!this.ruleSet[rule].call(null, input)) {
                                    return false;
                                }
                            }
                        }
                    }
                }
                
                //책엔 작성되어 있지 않지만 모든 유효성 체크가 완료된 것을 체크하기 위해 추가하였습니다.
                return true; 
            }
            
            // 검증 규칙
            // required : 필수 항목, 값이 있어야 함
            // alphabet : 알파벳만 입력되어야 함
            // number : 숫자만 입력되어야 함
            
            validator.decorate("required", function (input) {
                if (!input.value) {
                    console.log(input.name + " is required");
                    return false;
                }
                return true;
            });
            validator.decorate("alphabet", function (input) {
                let regex = /^[a-zA-Z\s]*$/;
                if (!regex.test(input.value)) {
                    console.log(input.name + " has to be only alphabets");
                    return false;
                }
                return true;
            });
            validator.decorate("number", function (input) {
                let regex = /^[0-9]*$/;
                if (!regex.test(input.value)) {
                    console.log(input.name + " has to be only numbers");
                    return false;
                }
                return true;
            });
        }());
        </script>
    </body>
</html>

 

결과

필수 항목을 모두 기입하지 않은 경우 

 

유효성체크를 통과하지 못한 경우

 

필수 항목을 모두 기입한 경우

 

#

참고도서 : 속깊은 자바스크립트 5.4. 데커레이터 패턴

참고할만한 문서 : ui.toast.com/weekly-pick/ko_20200102

728x90

댓글