8

ExtJS 4を使用していて、コンボのドロップダウンリストから現在選択されている値を非表示にする方法を探していますか?

したがって、これの代わりに(コンボボックスで現在選択されている「アラスカ」):

デフォルトのコンボボックスの動作

値のリストを次のようにしたいと思います。

ここに画像の説明を入力してください

私の場合、コンボボックスは編集できません(つまり、任意の値を入力できません)。選択した値を2回表示することはあまり意味がないと思います。1回は入力フィールドに、もう1回はドロップダウンリストに表示します。何が選択されているかはすでにわかります。ドロップダウンリストに、選択できる他のオプションのみを表示したいと思います。

これまでのところ、簡単な方法はわかりません。おそらく、開始するのに最適な場所はコンボボックスストアのフィルタリングですが、コンボボックスはライブ検索機能に独自のフィルターを使用します。

誰かがこの問題を考えましたか?私は何か変なことをしようとしていますか?関連するトピックが見つからないことに驚いています。

4

5 に答える 5

6

私はあなたがここで多くのオプションを持っている必要はないと思います...多分あなたはこのようなことをすることができます:

Ext.define('Your.company.Combo', {
    extend: 'Ext.form.field.ComboBox',
    alias: 'widget.specialcombo',

    /**
    * @cfg {boolean} hideActive
    * True to hide any selected record. Defaults to <tt>true</tt>.
    */
    hideActive: true,

    /**
    * @private {Ext.data.Model[]} hideActive
    * A Array of selected records.
    */


    initComponent: function () {
        this.selectedRecords = [];

        this.callParent(arguments);

        this.on('select', this.onSelectionChange, this);
    },

    /**
    * @private onChangeSelection
    * eventhandler selections
    */
    onSelectionChange: function (me, recs) {
        if(!me.hideActive)
            return;
        // write the current selected back to the store (you need to suspend autoSync if active)
        me.store.add(me.selectedRecords);
        // set the selected as new recordlist
        me.selectedRecords = recs;
        // remove the selected from the store
        me.store.remove(recs);
    }
});

その例は完全にテストされていません。ただし、ストアは主にテキストフィールドに直接接続されていないBoundListにバインドされているため、これは機能するはずです。ここでは一種のキャッシングを行っています。

于 2012-09-04T19:18:36.817 に答える
4

私はさらに単純に見える別の解決策を思いつきました、そして、速いテストは副作用を明らかにしません:

コンボボックスロジックはそのままにしておくことができますが、CSSを介して選択したアイテムを非表示にするだけです。

.x-boundlist-selected {
    display: none;
}

そして出来上がり、選択したアイテムが表示されません!これが本番コードでどれほど信頼できるかはわかりませんが、それでも検討する価値があると思います...


アップデート。Comboboxの構成フラグを介してこの動作を制御する場合の完全なソリューションは次のとおりです。

Ext.define('My.ComboBox',  {
    extend: 'Ext.form.field.ComboBox',

    /**
     * @cfg {Boolean} hideActive=true
     * When true, hides the currently selected value from the dropdown list
     */
    hideActive: true,

    /**
     * Internal method that creates the BoundList
     */
    createPicker: function() {
      var picker = this.callParent(arguments);

      // honor the hideActive flag
      if(this.hideActive) {
        picker.addCls('x-boundlist-hideactive');
      }

      return picker;
    }
});

CSSのどこか:

.x-boundlist-hideactive .x-boundlist-selected {
    display: none;
}

更新2.私のアプローチでUIの問題が見つかりました!

ドロップダウンリストから選択した項目を非表示にすると、キーボードナビゲーションに癖が生じます。要素は視覚的に非表示になっていますが、要素はまだ存在しており、上/下キーを押すとExtがその項目を選択します。視覚的には、ある時点で選択範囲が消え、次の表示要素に戻すにはもう一度上/下を押す必要があることを意味します。

これまでのところ、これに対する簡単な修正を見つけることができませんでした。私の最善の策itemSelectorは、バインドされたリスト(データビュー)を変更し.x-boundlist-item:not(.x-boundlist-selected)て、選択した要素がクエリに含まれないように設定することです。

セレクター自体は機能しますが、追加のクラス(選択したアイテムクラスを含む)がアイテムに適用される前にビューがこのセレクタークエリを実行するため、問題は解決しません(これはExt.view.AbstractView.refresh()で発生します)

また、この解決策では、コンボボックスの上にドロップダウンリストが表示されたときに、ドロップダウンリストが誤って配置されます。

私のアプローチは簡単すぎて完璧に機能できないと感じました:)

于 2012-09-06T07:19:05.650 に答える
2

私は@sraのソリューションの修正バージョンを使用することになりました:

Ext.define('My.ComboBox',  {
    extend: 'Ext.form.field.ComboBox',

    /**
     * @cfg {Boolean} hideActive=true
     * When true, hides the currently selected value from the dropdown list
     */
    hideActive: true,

    /**
    * @private {Ext.data.Model[]} selectedRecords
    * A Array of selected records, used when hideActive is true
    */

    initComponent: function() {
        this.selectedRecords = [];

        this.callParent();
    },


    setValue: function(value, doSelect) {
        var store = this.store;

        if(this.hideActive) {
            store.suspendEvents(false);
            // write the current selected back to the store (you need to suspend autoSync if active)
            // do this BEFORE callParent so the currently selected record would be found in the store
            store.add(this.selectedRecords);
        }

        this.callParent(arguments);

        if(this.hideActive) {
            // set the selected as new recordlist
            this.selectedRecords = this.valueModels;
            // remove the selected from the store
            store.remove(this.valueModels);
            store.resumeEvents();
            store.fireEvent('refresh', store);
        }

        return this;
    }

});

「非表示」ロジックは同じですsetValueが、コンボボックスが値で初期化される場合を含め、コンボの値をプログラムで設定するときにも機能することを確認するために、メソッドで実行するだけです。

UPDまた、store.add(this.selectedRecords);に呼び出す必要があるように見えます。そうしないと、同じ値を2回設定しようとすると、コンボボックスが奇妙に動作します(削除したためにストアでアクティブレコードが見つからないため、空白にリセットされます) )。選択したレコードを操作している最中にコンボボックスがドロップダウンリストと同期しようとすることによって引き起こされるいくつかの癖を防ぐためにストアのイベントを一時停止し、完了したら手動でストアのイベントをトリガーして、リストが最終的に更新されるようにします。これはパフォーマンスに影響を与える可能性がありますが、これまでのところ、より良い解決策はわかりません。 this.callParent(arguments);'refresh'

于 2012-10-19T10:30:36.090 に答える
2

ExtJS3私は他の人に基づいてこの答えを書きました。私にとっては素晴らしい作品ですが、あなたが探しているものから少し変更されています。

Name.space.name = new Ext.extend(Ext.form.ComboBox, {
    type: 'all',
    oldrec: null,
    store: null,
    constructor: function (config) {
        var me = this;
        if (config.type === 'all') {
            me.store = AllConditionStore;
        } else {
            me.store = ?.?('RuleParameterType');
        }
        config = Ext.apply({
            store: me.store,
            valueField: 'id',
            hideActive: true,
            triggerAction: 'all',
            lazyRender: true,
            allowBlank: false,
            mode: 'local',
            displayField: 'text',
            listeners: {
                select: function (me, recs, index) {
                    if (me.oldrec !== null)
                        me.store.add(me.oldrec);
                    me.oldrec = recs;
                    // remove the selected from the store
                    me.store.remove(recs);
                    // redo store
                }
            }
        }, config);
        ?.?.Parameter.superclass.constructor.call(this, config);
    }
});
于 2013-07-31T23:51:23.420 に答える
0

そこで、@ sraのソリューションを使用しましたが、少し変更を加えて、コンテンツをif(!me.hideActive):の下の適切な場所に追加しました。

if(me.selectedRecords[0]) {
    me.store.insert(me.selectedRecords[0].index,me.selectedRecords);
}

そうすれば、それらをボタンに追加しないでください。古い投稿であることは知っていますが、解決策を探している人々に役立つことを願っています。

于 2014-08-26T19:00:50.760 に答える