Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExtJS 4: How to know when any field in a form (Ext.form.Panel) changes?

Tags:

extjs

extjs4

I'd like a single event listener that fires whenever any field in a form (i.e., Ext.form.Panel) changes. The Ext.form.Panel class doesn't fire an event for this itself, however.

What's the best way to listen for 'change' events for all fields in a form?

like image 772
Clint Harris Avatar asked Dec 19 '11 19:12

Clint Harris


People also ask

What is the xType for EXT form Panel?

xType defines the type of Ext JS UI component, which is determined during rendering of the component. For example, the element can be a textbox for which we have xType as textField or the element can have a numeric value only for which we have Numeric xType.

What is the benefit of using Itemid?

The itemid global attribute provides microdata in the form of a unique, global identifier of an item. An itemid attribute can only be specified for an element that has both itemscope and itemtype attributes.

What is Itemid Extjs?

When you use an id for a component, there must be a single instance of this component, If you create another instance that has the same id, you will have problems as the DOM is confused. when you use itemId, it should be unique only within the component's immediate container.

What is Ext getCmp?

getCmp. will return you an item matching the id you passed it. This will be the fastest method to return an item. All items when created with an id are registered in a single object using their id as a key.


1 Answers

Update: Added a 3rd option based on tip in comments (thanks @innerJL!)

Ok, looks like there are at least two fairly simple ways to do it.

Option 1) Add a 'change' listener to each field that is added to the form:

Ext.define('myapp.MyFormPanel', {
  extend: 'Ext.form.Panel',
  alias: 'myapp.MyFormPanel',
  ...

  handleFieldChanged: function() { 
    // Do something
  },

  listeners: {
    add: function(me, component, index) {
      if( component.isFormField ) {
        component.on('change', me.handleFieldChanged, me);
      }
    }
  }
});

This has at least one big drawback; if you "wrap" some fields in other containers and then add those containers to the form, it won't recognize the nested fields. In other words, it doesn't do a "deep" search through the component to see if it contains form field that need 'change' listeners.

Option 2) Use a component query to listen to all 'change' events fired from fields in a container.

Ext.define('myapp.MyController', {
  extend: 'Ext.app.Controller',
  ...

  init: function(application) {
    me.control({

        '[xtype="myapp.MyFormPanel"] field': {
            change: function() {
              // Do something
            }
        }
    });
  }
});

Option 3) Listen for the 'dirtychange' fired from the form panel's underlying 'basic' form (Ext.form.Basic). Important: You need to make sure you must enable 'trackResetOnLoad' by ensuring that {trackResetOnLoad:true} is passed to your form panel constructor.

Ext.define('myapp.MyFormPanel', {
  extend: 'Ext.form.Panel',
  alias: 'myapp.MyFormPanel',
  constructor: function(config) {
    config = config || {};
    config.trackResetOnLoad = true;
    me.callParent([config]);

    me.getForm().on('dirtychange', function(form, isDirty) {
       if( isDirty ) {
            // Unsaved changes exist
        }
        else {
            // NO unsaved changes exist
        }
    });
  }
});

This approach is the "smartest"; it allows you to know when the form has been modified, but also if the user modifies it back to it's original state. For example, if they change a text field from "Foo" to "Bar", the 'dirtychange' event will fire with 'true' for the isDirty param. But if the user then changes the field back to "Foo", the 'dirtychange' event will fire again and isDirty will be false.

like image 164
Clint Harris Avatar answered Oct 18 '22 14:10

Clint Harris