web-dev-qa-db-ja.com

ExtJS 4:フォーム(Ext.form.Panel)のフィールドがいつ変更されたかを知る方法は?

フォーム(つまり、Ext.form.Panel)のanyフィールドが変更されるたびに起動する単一のイベントリスナーが欲しいのですが。ただし、Ext.form.Panelクラスは、これ自体のイベントを発生させません。

フォーム内のすべてのフィールドの「変更」イベントをリッスンする最良の方法は何ですか?

11
Clint Harris

更新:コメントのヒントに基づいて3番目のオプションを追加しました(@innerJLに感謝します!)

わかりました。少なくとも 2つの非常に簡単な方法があるようです。

オプション1)フォームに追加される各フィールドに「変更」リスナーを追加します。

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

これには少なくとも1つの大きな欠点があります。一部のフィールドを他のコンテナに「ラップ」してから、それらのコンテナをフォームに追加すると、ネストされたフィールドは認識されません。つまり、コンポーネントを「詳細に」検索して、「変更」リスナーが必要なフォームフィールドが含まれているかどうかを確認することはありません。

オプション2)コンポーネントクエリを使用して、コンテナ内のフィールドから発生するすべての「変更」イベントをリッスンします。

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

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

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

オプション3)フォームパネルの基礎となる「基本」フォーム(Ext.form.Basic)から発生する「dirtychange」をリッスンします。 重要:{trackResetOnLoad:true}がフォームパネルコンストラクターに渡されるようにして、「trackResetOnLoad」を有効にする必要があることを確認する必要があります。

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」イベントはisDirtyパラメータに対して「true」で発生します。ただし、ユーザーがフィールドbackを「Foo」に変更すると、「dirtychange」イベントが発生しますagain、isDirtyはfalseになります。

19
Clint Harris

クリントの答えを補足したいと思います。もう1つのアプローチがあります(そして私はそれがあなたの問題に最適だと思います)。 changeリスナーをフォームのデフォルト設定に追加するだけです。

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