読者です 読者をやめる 読者になる 読者になる

初心者のためのExtJS入門

ExtJSを使うので、ついでにまとめていきます

クラスのオーバーライド

今回はクラスのオーバーライドです。

クラスをオーバーライドすると、対象クラスのメソッドを上書きしたり、プロパティやメソッドを追加したりできます。

私がオーバーライドを使うのは↓のような場合です。

  • フレームワークが提供しているクラスに不具合があり修正が必要・・・
  • 良く使う機能を追加したい・・・
  • 必ず含めないといけないリクエストパラメータを追加したい・・・

オーバーライドしてみる

試しにExt.form.field.Textをオーバーライドしてみましょう。

app.jsonには↓の定義があり、オーバーライド用のファイルはoverrides、classic/overrides、modern/overridesディレクトリに作成していきます。

"overrides": [
    "overrides",
    "${toolkit.name}/overrides"
]

classicだけに適用したいので、classic/overridesにform/field/Text.jsを作成してみます。

f:id:sham-memo:20170205151622p:plain

最低限の記述は↓のようになります。overrideプロパティにオーバーライドしたいクラスを指定します。クラス名は何でも良いですが、私は大体、アプリケーション名.overrides.(オーバーライドするクラスのExtを除いた部分)とします。重複しないから。

/**
 * Ext.form.field.Textのオーバーライドクラス。
 *
 * @class Memo.overrides.form.field.Text
 * @override Ext.form.field.Text
 */
Ext.define('Memo.overrides.form.field.Text', {
    override: 'Ext.form.field.Text'
});

試しにpaddingを設定してみます。

/**
 * Ext.form.field.Textのオーバーライドクラス。
 *
 * @class Memo.overrides.form.field.Text
 * @override Ext.form.field.Text
 */
Ext.define('Memo.overrides.form.field.Text', {
    override: 'Ext.form.field.Text',

    padding: 20

});

↓こんな感じにpaddingが反映されてますね。テキストエリアはExt.form.field.Textを継承しているので、そちらも影響を受けているのが分かります。

f:id:sham-memo:20170205152437p:plain

特定の機能を追加してみる

私がオーバーライドで良く作成する処理を1つ紹介します。入力フィールドをclearable: trueにすると、値が入力されるとクリアボタンが表示されるようにしています。

/**
 * Ext.form.field.Textのオーバーライドクラス。
 *
 * @class Memo.overrides.form.field.Text
 * @override Ext.form.field.Text
 */
Ext.define('Memo.overrides.form.field.Text', {
    override: 'Ext.form.field.Text',

    /**
     * @cfg {Boolean} trueを設定するとクリア機能が利用できる。
     */
    clearable: false,

    // @override
    constructor: function(config) {
        var me = this;

        config = config || {};

        if (config.clearable) {
            config.triggers = Ext.apply(config.triggers || {}, {
                clear: {
                    weight: 0,
                    cls: Ext.baseCSSPrefix + 'form-clear-trigger',
                    hidden: true,
                    handler: 'onClearClick',
                    scope: 'this'
                }
            })
        }

        me.callParent(arguments);

        if (config.clearable) {
            me.on('change', 'onChange', me);
        }
    },

    // @override
    afterRender: function(){
        var me = this;
        me.callParent();

        me.onChange();
    },

    /**
     * クリアボタンクリック時の処理。
     */
    onClearClick : function(){
        this.setValue('');
    },

    /**
     * changeイベント発火時の処理。
     */
    onChange: function() {
        var me = this,
            value = String(me.getValue() || '');

        value.length > 0 ? me.showClearButton() : me.hideClearButton();
    },

    /**
     * クリアボタンを表示する
     */
    showClearButton: function() {
        var me = this;

        if(me.triggers.clear) {
            me.triggers.clear.show();
        }
    },

    /**
     * クリアボタンを非表示にする
     */
    hideClearButton: function() {
        var me = this;

        if(me.triggers.clear) {
            me.triggers.clear.hide();
        }
    }
});

f:id:sham-memo:20170205155216p:plain

便利な機能の1つだと思いますが、継承しているクラスにも影響するので、オーバーライドしても大丈夫か注意して使うようにしましょう。