ExtJs dependent field validation
Asked Answered
M

6

12

How do I validate one field which is dependent on another field?

{
  xtype:          'textfield',
  name:           'name2',
  vtype:          'type',      // how to write the validation code for this if it 
                               // depends on the value of another field?
  allowBlank:     false
}
Marquez answered 3/3, 2011 at 21:10 Comment(0)
S
26

By adding your own custom validator and therein perform your validation.

var field_one = new Ext.form.TextField({
    name: 'field_one',
    fieldLabel: 'Field one'
});

var field_two = new Ext.form.TextField({
    name: 'field_two',
    fieldLabel: 'Field two',
    validator: function(value){
        if(field_one.getValue() != value) {
            return 'Error! Value not identical to field one';
        } else {
            return true;
        }
    }
});
Spitler answered 3/3, 2011 at 21:23 Comment(3)
good answer, but how to perform the validation in another place, e.g inside the action listener of another button.Marquez
That's also possible but you'll have to get references to your elements through scope or Ext.getCmp() if you are in a button handler. And then perform the validation and manually mark the fields as invalid with field.markInvalid('...')Spitler
With regards to @Spitler comment about getting a reference. Chances are your fields are in the same container. So you can easily get a reference to the other field inside the validator function. this inside the function is the textfield on which the validator is configured. Get a reference to the other field using: var otherField = this.up().down('field[name=field_one]') (ExtJS 4)Keek
S
2

field definition:

....
monitorValid:     true,
....
}, {
  xtype:          'textfield',
  name:           'name1',
  ref:            'name1',

}, {
  xtype:          'textfield',
  name:           'name2',
  ref:            'name2',
  allowBlank:     false,
....

next in initComponent (or listener if you preffer):

this.name2.on ( 'change', this._validate_name2, this );

and define handler in FormPanel:

this._validate_name2: function ( ) {
   if ( this.name1.getValue () == this.name2.getValue () ) {
      this.name2.markInvalid ( 'field does not match name1' );
      this.name2.setValue ( null );
   }
}

"markInvalid () method does not cause the Field's validate method to return false if the value does pass validation. So simply marking a Field as invalid will not prevent submission of forms submitted with the Ext.form.Action.Submit.clientValidation option set."

For this reason combination allowBlank and setValue ( null ) will break validation

Sym answered 4/3, 2011 at 3:41 Comment(0)
D
2

I mocked up an example of how I'm doing this with comboboxes in Ext JS 5.1... it's easily portable to Ext 4 code, you'd just have to make use of initComponent instead of ViewController's init. Here's the code (and Fiddle):

Ext.application({
  name: 'Fiddle',

  launch: function() {
    Ext.define('MyComboViewController', {
      extend: 'Ext.app.ViewController',
      alias: 'controller.mycombo',
      init: function() {
        this.getView().setStore(this.createStore());
      },
      createStore: function() {
        var store = Ext.create('Ext.data.Store', {
          fields: [
            {name: 'disp', type: 'string'},
            {name: 'val', type: 'int'}
          ],
          data: [
            {disp: 'One', val: 1},
            {disp: 'Two', val: 2},
            {disp: 'Three', val: 3},
            {disp: 'Four', val: 4},
            {disp: 'Five', val: 5}
          ],
          proxy: {
            type: 'memory'
          }
        });
        return store;
      }
    });

    Ext.define('MyCombo', {
      extend: 'Ext.form.field.ComboBox',
      xtype: 'myCombo',
      controller: 'mycombo',
      displayField: 'disp',
      valueField: 'val',
      labelAlign: 'top',
      validateOnChange: false,
      typeAhead: true,
      queryMode: 'local'
    });

    Ext.define('MyCombosContainerViewController', {
      extend: 'Ext.app.ViewController',
      alias: 'controller.mycomboscontainer',
      init: function() {
        var startCombo = this.lookupReference('startCombo');
        var endCombo = this.lookupReference('endCombo');
        startCombo.validator = Ext.bind(this.comboValidator, this, [startCombo, endCombo]);
        endCombo.validator = Ext.bind(this.comboValidator, this, [startCombo, endCombo]);
      },
      comboValidator: function(startCombo, endCombo) {
        return startCombo.getValue() < endCombo.getValue();
      },
      onSelectComboBox: function(combo) {
        var startCombo = this.lookupReference('startCombo');
        var endCombo = this.lookupReference('endCombo');
        startCombo.validate();
        endCombo.validate();
      }
    });

    Ext.define('MyCombosContainer', {
      extend: 'Ext.form.FieldContainer',
      controller: 'mycomboscontainer',
      layout: {
        type: 'hbox',
        align: 'stretch'
      },
      items: [{
        xtype: 'myCombo',
        reference: 'startCombo',
        fieldLabel: 'Start',
        listeners: {
          select: 'onSelectComboBox'
        }
      }, {
        xtype: 'myCombo',
        reference: 'endCombo',
        fieldLabel: 'End',
        listeners: {
          select: 'onSelectComboBox'
        }
      }]
    });

    Ext.create('MyCombosContainer', {
      renderTo: Ext.getBody()
    });
  }
});
Dave answered 14/5, 2015 at 1:9 Comment(1)
Minor note: usually classes are defined outside of the call to Ext.applicationLenardlenci
M
0

To validate linked fields I usually create function (I add this to my Ext.lib.Validators class so I can call it in whole application) that returns an anonymous function with preconfigured scope and validation logic (so I can use it multiple times across my application).

Here is an example:

myValidator: function (firstFieldSelector, secondFieldSelector, thirdFieldSelector) {
    return function () {
        var firstField = Ext.ComponentQuery.query(firstFieldSelector)[0],
            secondField= Ext.ComponentQuery.query(secondFieldSelector)[0],
            thirdField= Ext.ComponentQuery.query(thirdFieldSelector)[0];

        if (firstField && secondField && thirdField) {
            // Validation logic here...
            if( true ) {
                return true;
            } else {
                return 'Error text here...';
            }
        } else {
            // Validator incorrectly configured, do not validate with it
            return true;
        }
    }
}

And here is an example fiddle with timespan selection.

Mcrae answered 8/12, 2015 at 15:35 Comment(0)
I
0

Generically - I would suggest to hook up change event listeners on all fields which needs to have cross validation. In change event handler we need to trigger validation on every other field which needs to validation with the field being modified. this approach works very well when you have a form and there are lots of fields and lots of validations needs to be done.

Ivanaivanah answered 9/9, 2019 at 18:33 Comment(0)
H
-1
{
        xtype: 'textfield',
        fieldLabel: 'National Tax Number / ID',
        labelWidth: 200,
        maxLength: 20,
        validator: function (enteredValue) {
            if (this.hasFocus === true) {
                return true;
            }
            if (Ext.isEmpty(enteredValue)) {
                return this.allowBlank ? true : VSpace.utils.i18n.localize('submission.main.step.account.fieldRequired.message', 'This field is required.');
            }
            if(!RegExp('[^a-zA-Z0-9]').test( enteredValue )) {
                return VSpace.utils.i18n.localize('submission.main.step.account.fieldRequired.message', 'This field is required.');;
            }
            return true;
        },
        bind: {
            value: '{step.account.account.vatCode}'
        }

    }
Hellfire answered 26/8, 2022 at 18:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.