web-dev-qa-db-ja.com

カスタムExtJSフォームフィールドコンポーネントを作成する方法は?

他のExtJSコンポーネント(例:TreePanel)を使用して、カスタムExtJSform fieldコンポーネントを作成します。どうすれば最も簡単にできますか?

Ext.form.field.Base のドキュメントを読みましたが、fieldSubTplでフィールド本体を定義したくありません。 ExtJSコンポーネントを作成するコードと、値を取得および設定する他のコードを作成したいだけです。

更新:要約された目的は次のとおりです。

  • この新しいコンポーネントは、フィールドとしてフォームGUIに収まる必要があります。さらにハッキングする必要なく、ラベルと他のフィールドと同じ配置(ラベル、アンカー)が必要です。

  • おそらく、getValue、setValueのロジックを作成する必要があります。私が管理しなければならないさらに隠されたフォームフィールドに物事をコピーする分離コードを作成するよりも、むしろこのコンポーネントに埋め込みたいと思います。

31
pcjuzer

@RobAgarの答えを拡張するために、ExtJS 3用に作成した非常にシンプルなDate Timeフィールドに従い、ExtJS 4用に作成したクイックポートです。重要なのは Ext.form.field.Field mixin。このミックスインは、次のような論理的な動作とフォームフィールドの状態に共通のインターフェイスを提供します。

フィールド値の取得メソッドと設定メソッド値と有効性の変更を追跡するイベントとメソッド検証をトリガーするメソッド

これは、複数のフィールドを組み合わせて、それらを1つのフィールドとして機能させるために使用できます。合計カスタムフィールドタイプについては、拡張することをお勧めします Ext.form.field.Base

ここに私が上で言及した例があります。 getterおよびsetter内でデータをフォーマットする必要がある日付オブジェクトのようなものであっても、これをどれだけ簡単に実行できるかがわかるはずです。

Ext.define('QWA.form.field.DateTime', {
    extend: 'Ext.form.FieldContainer',
    mixins: {
        field: 'Ext.form.field.Field'
    },
    alias: 'widget.datetimefield',
    layout: 'hbox',
    width: 200,
    height: 22,
    combineErrors: true,
    msgTarget: 'side',
    submitFormat: 'c',

    dateCfg: null,
    timeCfg: null,

    initComponent: function () {
        var me = this;
        if (!me.dateCfg) me.dateCfg = {};
        if (!me.timeCfg) me.timeCfg = {};
        me.buildField();
        me.callParent();
        me.dateField = me.down('datefield')
        me.timeField = me.down('timefield')

        me.initField();
    },

    //@private
    buildField: function () {
        var me = this;
        me.items = [
        Ext.apply({
            xtype: 'datefield',
            submitValue: false,
            format: 'd.m.Y',
            width: 100,
            flex: 2
        }, me.dateCfg),
        Ext.apply({
            xtype: 'timefield',
            submitValue: false,
            format: 'H:i',
            width: 80,
            flex: 1
        }, me.timeCfg)]
    },

    getValue: function () {
        var me = this,
            value,
            date = me.dateField.getSubmitValue(),
            dateFormat = me.dateField.format,
            time = me.timeField.getSubmitValue(),
            timeFormat = me.timeField.format;
        if (date) {
            if (time) {
                value = Ext.Date.parse(date + ' ' + time, me.getFormat());
            } else {
                value = me.dateField.getValue();
            }
        }
        return value;
    },

    setValue: function (value) {
        var me = this;
        me.dateField.setValue(value);
        me.timeField.setValue(value);
    },

    getSubmitData: function () {
        var me = this,
            data = null;
        if (!me.disabled && me.submitValue && !me.isFileUpload()) {
            data = {},
            value = me.getValue(),
            data[me.getName()] = '' + value ? Ext.Date.format(value, me.submitFormat) : null;
        }
        return data;
    },

    getFormat: function () {
        var me = this;
        return (me.dateField.submitFormat || me.dateField.format) + " " + (me.timeField.submitFormat || me.timeField.format)
    }
});
27
sra

へえ。バウンティを投稿した後、Ext.form.FieldContainerは、単なるfieldコンテナではなく、完全なcomponentコンテナなので、簡単な解決策があります。

必要なことは、FieldContainerを拡張し、initComponentをオーバーライドして子コンポーネントを追加し、setValuegetValueおよび検証メソッドを実装することです。値のデータ型。

値が名前/値のペアオブジェクトのリストであるグリッドを使用した例を次に示します。

Ext.define('MyApp.widget.MyGridField', {
  extend: 'Ext.form.FieldContainer',
  alias: 'widget.mygridfield',

  layout: 'fit',

  initComponent: function()
  {
    this.callParent(arguments);

    this.valueGrid = Ext.widget({
      xtype: 'grid',
      store: Ext.create('Ext.data.JsonStore', {
        fields: ['name', 'value'],
        data: this.value
      }),
      columns: [
        {
          text: 'Name',
          dataIndex: 'name',
          flex: 3
        },
        {
          text: 'Value',
          dataIndex: 'value',
          flex: 1
        }
      ]
    });

    this.add(this.valueGrid);
  },

  setValue: function(value)
  {
    this.valueGrid.getStore().loadData(value);
  },

  getValue: function()
  {
    // left as an exercise for the reader :P
  }
});
4
Rob Agar

質問は漠然と尋ねられたため、ExtJS v4の基本パターンのみを提供できます。

あまり具体的ではない場合でも、次のようにかなり普遍的であるという利点があります。

Ext.define('app.view.form.field.CustomField', {
    extend: 'Ext.form.field.Base',
    requires: [
        /* require further components */
    ],

    /* custom configs & callbacks */

    getValue: function(v){
        /* override function getValue() */
    },

    setValue: function(v){
        /* override function setValue() */
    },

    getSubTplData: [
       /* most likely needs to be overridden */
    ],

    initComponent: function(){

        /* further code on event initComponent */

        this.callParent(arguments);
    }
});

ファイル/ext/src/form/field/Base.jsは、オーバーライド可能なすべての構成と機能の名前を提供します。

3
Martin Zeitler

私はこれを数回しました。私が使用する一般的なプロセス/擬似コードは次のとおりです。

  • 最も有用な再利用を提供するフィールドの拡張機能を作成します(文字列値を取得/設定するだけの場合は通常Ext.form.TextField)
  • フィールドのafterrenderで、テキストフィールドを非表示にし、this.wrap = this.resizeEl = this.positionEl = this.el.wrap()を使用してthis.elを囲む要素を作成します
  • コンポーネントをthis.wrapにレンダリングします(例:構成でrenderTo: this.wrapを使用)
  • getValuesetValueをオーバーライドして、手動でレンダリングしたコンポーネントと通信します
  • フォームのレイアウトが変更された場合、resizeリスナーで手動でサイズ変更する必要がある場合があります
  • beforeDestroyメソッドで作成したコンポーネントをクリーンアップすることを忘れないでください!

これらの種類の作業が簡単なExtJS 4にコードベースを切り替えるのが待ち遠しいです。

幸運を!

3
Sean Adkinson

http://docs.sencha.com/ext-js/4-0/#/api/Ext.form.field.Base のドキュメントに従ってください

このコードは、言語を選択するための再利用可能なTypeAhead/Autocompleteスタイルフィールドを作成します。

var langs = Ext.create( 'Ext.data.store', {
    fields: [ 'label', 'code' ],
    data: [
        { code: 'eng', label: 'English' },
        { code: 'ger', label: 'German' },
        { code: 'chi', label: 'Chinese' },
        { code: 'ukr', label: 'Ukranian' },
        { code: 'rus', label: 'Russian' }
    ]
} );

Ext.define( 'Ext.form.LangSelector', {
    extend: 'Ext.form.field.ComboBox',
    alias: 'widget.LangSelector',
    allowBlank: false,
    hideTrigger: true,
    width: 225,
    displayField: 'label',
    valueField: 'code',
    forceSelection: true,
    minChars: 1,
    store: langs
} );

Xtypeをウィジェット名に設定するだけで、フォームでフィールドを使用できます。

{
    xtype: 'LangSelector'
    fieldLabel: 'Language',
    name: 'lang'
}
2
James Linden

回答の多くは、Mixin Ext.form.field.Fieldを使用するか、ニーズに合った既に作成されたクラスを拡張するだけです。これは問題ありません。

しかし、setValueメソッドを完全に上書きすることはお勧めしません。それはIMOが本当に悪いフォームです!

値を設定して取得するだけでなく、それを完全に上書きする場合よりもはるかに多くのことが起こります。たとえば、ダーティ状態やrawValueの処理などを台無しにしてしまいます。

ここでの2つのオプションは、1つは宣言したメソッド内でcallParent(arguments)を呼び出して物事を合理化するか、最後に継承したメソッドを取得した場所(mixinまたはextend)から適用することです。

しかし、すでに作成されたメソッドが舞台裏で行うことを考慮せずに上書きしないでください。

また、新しいクラスで他のフィールドタイプを使用する場合は、isFormFieldプロパティをfalseに設定することを忘れないでください。そうしないと、フォームのgetValuesメソッドがこれらの値を取得してemで実行します。

1
Splynx