ExtJS 4: Как узнать, когда изменяется какое-либо поле в форме (Ext.form.Panel)?

Мне нужен один прослушиватель событий, который срабатывает всякий раз, когда изменяется какое-либо поле в форме (т.е. Ext.form.Panel). Однако класс Ext.form.Panel не запускает событие для этого самого.

Какой лучший способ прослушать события "изменения" для всех полей в форме?

Ответ 1

Обновление. Добавлен третий вариант, основанный на подсказке в комментариях (спасибо @innerJL!)

Хорошо, похоже, есть хотя бы два довольно простых способа сделать это.

Вариант 1) Добавьте слушателя 'change' для каждого поля, которое добавлено в форму:

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);
      }
    }
  }
});

У этого есть хотя бы один большой недостаток; если вы "обертываете" некоторые поля в других контейнерах, а затем добавляете эти контейнеры в форму, они не будут распознавать вложенные поля. Другими словами, он не выполняет "глубокий" поиск через компонент, чтобы увидеть, содержит ли он поле формы, которое нуждается в "изменении" прослушивателей.

Вариант 2) Используйте компонентный запрос для прослушивания всех событий "изменения", запущенных из полей в контейнере.

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

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

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

Вариант 3) Слушайте "dirtychange" , снятый с панели формы, лежащей в основе "базовой" формы (Ext.form.Basic). Важно. Необходимо убедиться, что вы должны включить 'trackResetOnLoad', гарантируя, что {trackResetOnLoad: true} передается в конструктор панели формы.

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
        }
    });
  }
});

Этот подход является "самым умным"; он позволяет узнать, когда форма была изменена, а также если пользователь изменяет ее обратно в исходное состояние. Например, если они изменяют текстовое поле от "Foo" до "Bar", событие "dirtychange" срабатывает с "true" для параметра isDirty. Но если пользователь затем изменит поле на "Foo", событие "dirtychange" снова запустится, а isDirty будет false.

Ответ 2

Я хочу дополнить ответ Клинта. Существует еще один подход (и я считаю, что это лучше для вашей проблемы). Просто добавьте change прослушиватель, чтобы сформировать конфигурацию по умолчанию:

Ext.create('Ext.form.Panel', {
    // ...
    defaults: {
        listeners: {
            change: function(field, newVal, oldVal) {
                //alert(newVal);
            }
        }
    },
    // ...
});