javascript-praktikada--oz-form-validatorumuzu-yaziriq

Javascript Praktikada: Öz form validatorumuzu yazırıq

Hazırladığımız əksər saytlarda Javascript dilini bütün potensialı ilə istifadə edə bilmirik. Bu səbəbdən əksər Frontend developerlər sadəcə JS dilində minimal biliklərlə məhdudlaşmalı olurlar ya da ki dərinə getdikcə öyrəndiklərini praktikada istifadə edəcək yerlər tapmaqda çətinlik çəkirlər. Bunun bir çox səbəbləri var:

1)Sayt hazırlayarkən əksər modullar plugin olaraq qoşulduğundan əlavə birşeylər yazmağa çox az ehtiyac olur

2)Səhifədə adəti üzrə təmiz(pure) JS yox, Jquery və.s kitabxanalar istifadə olunur.

               Bu səbəbdən Javascript dilində öyrənilən bir çox mövzular sadəcə teoriyada qalır və praktikaya tətbiq etmək demək olar ki, əksər hallarda mümkün olmur.

PS:Brain2brain saytında bütün kod nümunələri təmiz(Pure) Javascriptdə yazılır və yazılmağa davam edəcək.

               Bugünki məqaləmizin əsas məqsədi Javascript dilini praktika etməkdir. Yazacağımız PJFormValidator( Pure Javascript Form Validator) vasitəsilə validasiya modulu düzəldəcəyik. Validasiya modulumuz aşağıdakı funksionallığı yerinə yetirir:


1)Clean formada istənilən html formanı vailidasiya edə bilir

2) 3 dildə validasiya prosesini aparır.

3) Rahat şəkildə istifadəçiyə yeni yoxlama qaydaları əlavə etməyə imkan yaradır.


Bu validator ilə aşağıdakı JS mövzularını praktikada tətbiq etmək olacaq:

1)JS Obyekt konstruktorlar

2)JS obyekt konfiqurasiyalar

3)Callback-lər

4)OOP İncapsulyasiya

5)Təmiz/Səlis kod yaza bilmə vərdişləri

 Validatoru tətbiq etmək üçün ilk öncə form hazırlamaq lazımdır. Formdakı inputları validasiya etmək üçün klaslardan istifadə olunacaq. Misalçün əgər hər hansı bir inputa “email” klası yazılıbsa bizim validator həmin inputun dəyərinin düzgün email olub-olmadığını yoxlayacaq. PJFormValidator default olaraq aşağıdakı klaslar(rule) üzrə validasiya apara bilir:


'required’ ------> ‘Xana boş ola bilməz!!',

'min-len-’ ------> ‘Sözün uzunluğu minimum `x` olmalıdır',

'max-len-’ ------> ‘Sözün uzunluğu maksimum `x` olmalıdır',

'num-min-’ ------> ‘Ədədin minimum dəyəri `x` olmalıdır',

'num-max-’ ------> ‘Ədədin maksimal dəyəri `x` olmalıdır',

'number’ ------> ‘Ədəd olmalıdır',

'email'-----> ‘Email duzgun deyil’


Əgər inputa min-len-6 klası yazsaq həmin inputda simvolların sayının minimum 6 ədəd olduğunu yoxlayacaq.

Hər bir input-da mütləq şəkildə data-validation-error adlı atribut verilməlidir. Həmin atribut hesabına error mesajlarının hansı elementdə əks olunacağını müəyyən edirik.

 

PS: kodların tamamına github adresimizdən baxa bilərsiniz.

               Html formamız aşağıdakı kimi olacaq.

Formu validasiya etmək üçün validator obyektimizdən istifadə edirik. Validator obyektinin validateForm metodu vasitəsilə formun identifikatorunu(id) metoda göndərərək həmin formu validasiya etmək olur.

Validator default olaraq validasiya səhvlərini ingilis dilində göstərir. Əgər dili dəyişmək lazımdırsa ozaman configLanguage metodundan istifadə edirik. Bu metoda dəstəklənən dillərdən birini (ru,en və az) birini verərək error mesajlarının həmin dildə görünməsini təmin etmək olar.

 //səhifənin tam yüklənməyini gözlə
 document.addEventListener('DOMContentLoaded', function() {
             
             // btn_validate düyməsinə klik etdikdə..
            document.getElementById('btn_validate').addEventListener('click', function(e) {
               
               //default behaviour ləğv edilsin
                e.preventDefault();
               
                //validatorun dilini rus dilinə quraşdır
                validator.configLanguage('ru');

                //identifikatoru validatable-form olan formu validasiya et.
                validator.validateForm('validatable-form');

            });

        })

Validator obyektini işə salmaq üçün validationConfig obyektinə ehtiyac var. Həmin obyektin işi dillərə görə error mesajlarını tənzimləməkdən ibarətdir. Bu obyektin interfeysindəki addValidationConfiguration metodu vasitəsilə istənilən dildə(ru,en və az) yeni bir rule(yoxlama qaydası) müəyyən edə bilərik.

let validationConfig = {
    isLangExistsfunction(lang{
        let isExists = false;
        for (let _lang in this.langs) {
            if (_lang == lang) {
                isExists = true;
                break;
            }
        }
        return isExists;
    },
    addValidationConfigurationfunction(lang, configClass, errorMessage{
        if (!this.isLangExists(lang))
            throw new Error('given language is not exists');
        this.langs[lang][configClass] = errorMessage;
    },
    getRuleValueByLangfunction(lang, rulename{
        return this.langs[lang][rulename];
    },
    langs: {
        az: {
            'required''Xana boş ola bilməz!!',
            'min-len-''Sözün uzunluğu minimum `x` olmalıdır',
            'max-len-''Sözün uzunluğu maksimum `x` olmalıdır',
            'num-min-''Ədədin minimum dəyəri `x` olmalıdır',
            'num-max-''Ədədin maksimal dəyəri `x` olmalıdır',
            'number''Ədəd olmalıdır',
            'email'"Email duzgun deyil"
        },
        ru: {
            'required''Поля должен быть заполнено',
            'min-len-''Минимальный длина слова должен быть `x`',
            'max-len-''Максимальная длина слова должен быть `x`',
            'num-min-''Минимальная значения число должен быть `x`',
            'num-max-''Максимальная значения число должен быть `x`',
            'number''Должен быть число',
            'email'"неправильно указан email"
        },
        en: {
            'required''Input cant be empty',
            'min-len-''Minimum length of the input must be `x`',
            'max-len-''Maximum length of the input must be `x`',
            'num-min-''Minimum size of number must be `x`',
            'num-max-''Maximum size of number must be `x`',
            'number''Must be only number!!',
            'email'"Email is not valid"
        }
    }
};

 Misalçün mən inputa istənilən bir klas (milsalçün mx-m-5) əlavə edə bilər və addValidationConfiguration metodu vasitəsilə göstərə bilərəmki mx-m- filan error deməkdir.

   validator.addValidationConfiguration('az', 'mx-m-', 'Hər hansı bir error mesajini buradan verəcəm');

Rule əlavə edərkən konstantlar nəzərə alınmır. Həmin konstantlar sadəcə validasiya zamanı çağrılıb istifadə olunur. Misal : Əgər min-len-7 yazılıbsa ozaman yoxlama qaydası (rule) sadəcə min-len- olacaq. 7 burada konstantdır və escape olunur.

  validator.addValidationRule('mx-m-', function(originalValue, errorOn, errorMessage, ruleValue) {
                    if (true) {
                        this._sendErrorToElement('mx-m-', errorOn, errorMessage);
                    }
                });

          Validatorun işləmə alqoritmini mətn formatında aşağıdakı kimi təsvir edə bilərik:

1)     Ötürülən id-yə uyğun formanın obyektini al

2)     Həmin formadakı bütün inputları götür

3)     Error mesajlarını harada əks etdirəcəyiksə həmin elementin innerHtml-ni təmizlə

4)     Hər bir inputun bütün klaslarını al

5)     Həmin klasa uyğun rule olub olmadığını yoxla

6)     Əgər belə bir rule varsa ozaman onun rəqəmini almağa çalış(min-len-6 dan 6 rəqəmini götür)

7)     Rule-u icra et

Yuxarıda qeyd olunan alqoritmik ardıcıllığı aşağıdakı kod nümunəsi özündə saxlayır.

    this.validateForm = function(formId{
        let formForValidate = document.getElementById(formId);
        if (formForValidate == null) {
            throw new Error('given form doesnt exist');
        } else {
            let inputsForValidate = this._getInputsForValidate(formForValidate);
            for (let input of inputsForValidate) {
                let errorOccuredOn = this._getValidationErrorElement(input);
                this._resetHtml(errorOccuredOn);
                let inputClAttributes = this._getAllClassAttributes(input);
                for (let inputClAttr of inputClAttributes) {
                    let ruleName = this._getRule(inputClAttr);
                    if (ruleName != null) {
                        let ruleValue = this._getRuleValue(inputClAttr, ruleName);
                        let formalizeErrorMessage = this._makeFormattedErrorMessage(inputClAttr, this._validationConfig.getRuleValueByLang(this._lang, ruleName));
                        this._rules.executeRule(ruleName, input.value, errorOccuredOn, formalizeErrorMessage, ruleValue);
                    }


                }
            }
        }
    }

 

ruleTypes adlanan obyektimiz bütün rule-ları saxlayır və validasiya məhz buradan aparılır.

   this._rules = {
            executeRulefunction(ruleName, value, errorOn, formalizedErrorMessage, ruleValue{
                this.ruleTypes[ruleName](value, errorOn, formalizedErrorMessage, ruleValue);
            },
            ruleTypes: {
                _createErrorContainerfunction(key, errorMessage{
                    let errorSpan = document.createElement('span');
                    errorSpan.className = `error-${key}`;
                    errorSpan.innerText = errorMessage;
                    return errorSpan;
                },
                _isNotaNumberfunction(val{
                    return isNaN(Number(val));
                },
                _isEmptyfunction(val{
                    return (!val || 0 === val.length);
                },
                _isValidEmailfunction(email{
                    let pattern = /^[^\[email protected]][email protected][^\[email protected]]+\.[^\[email protected]]+$/;
                    return pattern.test(email);
                },
                _IsTruefunction(callback{
                    if (callback())
                        return true;
                    else return false;
                },
                _sendErrorToElementfunction(className, errorOn, errorMessage{
                    let errorSpan = this._createErrorContainer(className, errorMessage);
                    document.getElementById(errorOn).appendChild(errorSpan);
                },
                'number'function(originalValue, errorOn, errorMessage, ruleValue{
                    if (this._isNotaNumber(originalValue)) {
                        this._sendErrorToElement('number', errorOn, errorMessage);
                    }
                },
                'required'function(originalValue, errorOn, errorMessage, ruleValue{
                    if (this._isEmpty(originalValue)) {
                        this._sendErrorToElement('required', errorOn, errorMessage);
                    }
                },
                'email'function(originalValue, errorOn, errorMessage, ruleValue{
                    if (this._isEmpty(originalValue) || !this._isValidEmail(originalValue)) {
                        this._sendErrorToElement('email', errorOn, errorMessage);
                    }
                },
                'min-len-'function(originalValue, errorOn, errorMessage, ruleValue{
                    if (this._isEmpty(originalValue) || this._IsTrue(() => originalValue.length < parseInt(ruleValue))) {
                        this._sendErrorToElement('min-len', errorOn, errorMessage);
                    }
                },
                'max-len-'function(originalValue, errorOn, errorMessage, ruleValue{
                    if (this._isEmpty(originalValue) || this._IsTrue(() => originalValue.length > parseInt(ruleValue))) {
                        this._sendErrorToElement('max-len', errorOn, errorMessage);
                    }
                },
                'num-min-'function(originalValue, errorOn, errorMessage, ruleValue{
                    if (this._isEmpty(originalValue) || this._IsTrue(() => parseInt(originalValue) < parseInt(ruleValue))) {
                        this._sendErrorToElement('num-min', errorOn, errorMessage);
                    }


                },
                'num-max-'function(originalValue, errorOn, errorMessage, ruleValue{
                    if (this._isEmpty(originalValue) || this._IsTrue(() => parseInt(originalValue) > parseInt(ruleValue))) {
                        this._sendErrorToElement('num-max', errorOn, errorMessage);
                    }


                }
            }
        }

Ruletypes obyektimizdə bəzi funksionallıqlar varki onlar rule deyillər. Ona görə Object.defineProperties ilə onların sadalanmasının qarşısını alırıq.

  Object.defineProperties(this._rules.ruleTypes, {
            "_createErrorContainer": {
                enumerablefalse,
                configurablefalse
            },
            "_isNotaNumber": {
                enumerablefalse,
                configurablefalse
            },
            "_isEmpty": {
                enumerablefalse,
                configurablefalse
            },
            "_isValidEmail": {
                enumerablefalse,
                configurablefalse
            },
            "_IsTrue": {
                enumerablefalse,
                configurablefalse
            },
            "_sendErrorToElement": {
                enumerablefalse,
                configurablefalse
            }
        });

Vaidatorumuz formu validasiya etdikdə belə bir şəkillə rastlaşırıq.

 PS: kodların tamamına github adresimizdən baxa bilərsiniz.

              


Tural

Tural Süleymani

Süleymani Tural Microsoft-un MCSD statuslu mütəxəssisidir, 2008-ci ildən bu yana proqramlaşdırma üzrə tədris aparır

Müəllifin bu dildə ən son postları

Bu yazıları da bəyənə bilərsiniz