Multiple validation: wiele vtype dla textfield w Ext JS 4

Multiple validation: wiele vtype dla textfield w Ext JS 4

Witam, w tym artykule pokażę ci implementację kilku vtype w Ext JS 4 jednocześnie. W moim poprzednim poście pisałem o własnych vtype i użyłem jako przykładu numeru PIN ponieważ niektóre banki nie pozwalają w kodach mieć identycznych numerów (takich jak 1111, 2222, itd.) dlatego tutaj też posłużę się tym przykładem. Poprzedni post znajduje się tutaj:

Ext JS 4 Custom Validation: tworzenie własnej walidacji vtype

Tym razem będzie to już bardziej zaawansowany przykład niż poprzedni. Dobrze, tutaj użyję walidacji aby sprawdzić czy wartość jest liczbą oraz czy wszystkie cyfry nie są identyczne.

Eksperymentalna forma wygląda następująco:

22-extjs4

A kod wygląda tak jak poniżej:

Ext.define('DevJS.view.users.Add', {
    extend: 'Ext.window.Window',
    alias: 'widget.usersAdd',

    height: 225,
    width: 369,
    resizable: false,
    title: 'Add user',
    modal: true,

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            items: [
                {
                    xtype: 'form',
                    bodyPadding: 20,
                    title: '',
                    defaults: { // defaults are applied to items, not the container
                        allowBlank: false,
                        allowOnlyWhitespace: false,
                        msgTarget: 'side',
                        xtype: 'textfield',
                        anchor: '100%'
                    },
                    items: [
                        {
                            fieldLabel: 'Login',
                            name: 'login',
                            minLength: 4
                        },
                        {
                            fieldLabel: 'First Name',
                            name: 'firstName'
                        },
                        {
                            fieldLabel: 'Last Name',
                            name: 'lastName'
                        },
                        {
                            fieldLabel: 'Email',
                            name: 'email',
                            vtype: 'email'
                        },
                        {
                            fieldLabel: 'PIN Number',
                            name: 'pin',
                            minLength: 4,
                            maxLength: 4
                        },
                        {
                            xtype: 'button',
                            anchor: 0,
                            itemId: 'save',
                            text: 'Save'
                        },
                        {
                            xtype: 'button',
                            anchor: 0,
                            itemId: 'cancel',
                            text: 'Cancel'
                        }
                    ]
                }
            ]
        });

        me.callParent(arguments);
    }

});

Implementacja multi vtype

Pierwszy plik to nasze custom vtypes w katalogu app/lib/form/field:

Ext.define('DevJS.lib.form.field.VTypes', {

    pin: /(?!(.)\1\1).{3}/,
    digits: /[0-9]+$/,

    init: function () {
        var me = this;

        //pin number
        this.pinFn();
        //only digits
        this.digitsFn();
        //etc..
    },
    pinFn:function () {
        var me = this;

        Ext.apply(Ext.form.field.VTypes, {
            pin:function (val, field) {
                //check value
                return me.pin.test(val);
            },
            pinText: 'Characters cannot be identical'
        });
    },
    digitsFn:function () {
        var me = this;

        Ext.apply(Ext.form.field.VTypes, {
            digits:function (val, field) {
                //check value
                return me.digits.test(val);
            },
            digitsText: 'Only numbers are allowed'
        });
    }
});

Aby to zrobić musimy podpiąć się pod obiekt Ext.form.field.VTypes.

//Ext.form.field.VTypes jest obiektem singleton

//Dobrą praktyką jest właśnie utworzenie nowego pliku o nazwie VTypes.js w katalogu lib

Ważna kwestia tutaj jest taka aby przedrostek zmiennej Text nazywał się tak samo jak funkcja, w tym przypadku jest to pinText oraz digitsText. A wynik twojej funkcji powinien zwracać true (poprawnie) lub false (niepoprawnie). Jeśli chcesz możesz inicjalizować kolejne vtype w funkcji init.

Aby zaimplementować twoj plik otwórz klasę DevJS.Application (app/application.js). Następnie dodaj do funkcji launch następującą linię:

Ext.create('DevJS.lib.form.field.VTypes').init();

i proszę dodaj do tablicy requires string z nazwą pliku:


requires: [
    'DevJS.lib.form.field.VTypes'
 ]

Twoje nowe typy walidacji powinny być już zaimplementowane i możesz ich używać w swojej aplikacji.

Ale jak użyć kliku vtype w jednym textfield?

Aby to zrobić możesz nadpisać domyślną metodę getErrors() w Ext.form.field.Text która jest odpowiedzialna za walidację.

//Pamiętaj, że nadpisywanie tej klasy może być niebezpieczne, szczególnie kiedy zmieniamy biblioteki których używamy ale jeśli jesteś pewien, że to szybko nie nastąpi możesz nadpisać klasę Ext.form.field.Text

Moja metoda znajduje się w tym pliku (app/lib/form/field/override/Text.js):

Ext.define('DevJS.lib.form.field.override.Text', {
    override: 'Ext.form.field.Text',

    getErrors: function(value) {
        var me = this,
            errors = me.callSuper(arguments),
            validator = me.validator,
            vtype = me.vtype,
            vtypes = Ext.form.field.VTypes,
            regex = me.regex,
            format = Ext.String.format,
            msg, trimmed, isBlank;

        value = value || me.processRawValue(me.getRawValue());

        if (Ext.isFunction(validator)) {
            msg = validator.call(me, value);
            if (msg !== true) {
                errors.push(msg);
            }
        }

        trimmed = me.allowOnlyWhitespace ? value : Ext.String.trim(value);

        if (trimmed.length < 1 || (value === me.emptyText && me.valueContainsPlaceholder)) {
            if (!me.allowBlank) {
                errors.push(me.blankText);
            }
            // If we are not configured to validate blank values, there cannot be any additional errors
            if (!me.validateBlank) {
                return errors;
            }
            isBlank = true;
        }

        // If a blank value has been allowed through, then exempt it dfrom the minLength check.
        // It must be allowed to hit the vtype validation.
        if (!isBlank && value.length < me.minLength) {             errors.push(format(me.minLengthText, me.minLength));         }         if (value.length > me.maxLength) {
            errors.push(format(me.maxLengthText, me.maxLength));
        }

        switch(typeof vtype)
        {
            case 'string':
                if (!vtypes[vtype](value, me)) {
                    errors.push(me.vtypeText || vtypes[vtype +'Text']);
                }
                break;
            case 'object':
                Ext.Array.each(vtype, function(v){
                    if (!vtypes[v](value, me)) {
                        errors.push(me.vtypeText || vtypes[v +'Text']);
                    }
                });
                break;
        }

        if (regex && !regex.test(value)) {
            errors.push(me.regexText || me.invalidText);
        }

        return errors;
    }
});

Kod dla funkcji getErrors() możesz znaleść we wspomnianym już pliku (ext/src/form/field/Text.js). Zamieniłem te linie:

        if (vtype) {
            if (!vtypes[vtype](value, me)) {
                errors.push(me.vtypeText || vtypes[vtype +'Text']);
            }
        }

na poniższe:

        switch(typeof vtype)
        {
            case 'string':
                if (!vtypes[vtype](value, me)) {
                    errors.push(me.vtypeText || vtypes[vtype +'Text']);
                }
                break;
            case 'object':
                Ext.Array.each(vtype, function(v){
                    if (!vtypes[v](value, me)) {
                        errors.push(me.vtypeText || vtypes[v +'Text']);
                    }
                });
                break;
        }

Użycie tego sposobu pozwala na dodanie funkcjonalności do istniejącej klasy. Chciałbym zwrócić uwagę na jeszcze jedną kwestię, która tutaj się zmieniła, chodzi o poniższą linię:

errors = me.callParent(arguments),

zamieniłem na następującą:

errors = me.callSuper(arguments),

Możesz to zrobić tylko gdy używasz wersji Ext JS 4.1.3 lub późniejszych. Ta linia pozwala na ominięcie nadpisanej metody i wywołanie implementacji superklasy. Więcej informacji możesz znaleść tutaj:

Ext.Base method callSuper

Następnie, proszę dodaj do tablicy requires (app/application.js) następującą nazwę pliku:

requires: [
    'DevJS.lib.form.field.VTypes',
    'DevJS.lib.form.field.override.Text'
 ]

Ostatnia rzecz, zmiana konfiguracji pola pin textfield:


                        {
                            fieldLabel: 'PIN Number',
                            name: 'pin',
                            minLength: 4,
                            maxLength: 4,
                            vtype: ['pin', 'digits']
                        }

Teraz możesz używać wielu vtype w całej aplikacji! Możesz użyć standardowego sposobu poprzez “string”  lub skorzystać już z drugiego poprzez “array” i ustawić więcej niż jeden.

Dobrze, czas na pokaz. Sprawdźmy czy działa. Rezultat powinien wyglądać jak poniższe zdjęcia:

a) wbudowana walidacja email

25-extjs4

b) wiele vtypes w jednym polu

26-extjs4

27-extjs4

c) oraz poprawne wartości

28-extjs4

Jak widać działa poprawnie. W jednym z moich następnych postów pokażę Ci jak można przekazać parametry w swoich vtypes ponieważ niektóre walidacje wymagają dodatkowych parametrów. Udanej zabawy i do później.

Komentarze:

Zostaw odpowiedź

Proszę wypełnij wymagane pola aby dodać komentarz.


Drag circle to the rectangle on the right!

Wyślij