ExtJS - использование пользовательского TriggerField в качестве GridEditor - PullRequest
2 голосов
/ 05 июня 2009

Итак, я разместил эту статью на прошлой неделе на форумах ExtJS, но никто не ответил, и я немного схожу с ума, пытаясь понять:

Я довольно плохо знаком с ExtJS (только что изучил его на прошлой неделе для работы), но я уже довольно давно работаю с другими библиотеками JavaScript. Я делаю пользовательский элемент управления для редактирования списка атрибутов (в настоящее время заполняется запросом JSON). Я использую PropertyGrid с пользовательским GridEditor (созданным путем расширения различных полей Ext.form). Все мои настраиваемые поля работают, кроме одного, который является редактором повторяющихся значений. По сути, поле будет передаваться в виде простого 2d массива пары ключ / значение по запросу JSON, который отображается в EditorGridPanel (внутри созданного мной Ext.Window).

Вот раздел запроса JSON, который определяет редактор повторяющихся значений:

{
    key: 'Repeating',
    type: 'repeating',
    category: 'Category A',
    options: {
        dataArray: [
            {key: 'key A', value: 'value A'}, 
            {key: 'key B', value: 'value B'}, 
            {key: 'key C', value: 'value C'}
        ]
    }
}

Клавиша - это имя поля (отображается в левом столбце PropertyGrid). Тип сообщает функции, которая создает все редакторы сетки, какой тип пользовательского редактора использовать. Категория используется для определения того, к какой PropertyGrid добавлен GridEditor (у меня есть несколько PropertyGird, все они содержатся в Panel с макетом: «acordion»). Все в options добавляется в расширенное поле Ext.form при его создании.

Итак, dataArray присоединен к моему повторяющемуся редактору значений для настройки начальных пар ключ / значение и для сохранения массива, переданного обратно в GridEditor посредством Ext.Window, используемого для его редактирования.

После некоторых экспериментов я решил использовать TriggerField в качестве GridEditor для моего повторяющегося типа значения. Вот код для определения повторяющегося поля значения:

Ext.form.customFields = {
    'repeating': Ext.extend(Ext.form.TriggerField, {
        triggerClass: 'x-form-edit-trigger',
        enableKeyEvents: true
    })
};

А вот код, который его устанавливает:

Ext.form.customFields['repeating'] = Ext.extend(Ext.form.customFields['repeating'], {
    onTriggerClick: function()
    {
        this.editorWindow.show();
    },

    listeners: {
        'render': function(field)
        {
            field.editorWindow = new Ext.MultiSelectWindow({
                data: field.dataArray,
                parent: field
            });
        },
        'keydown': function(field, event)
        {
            event.stopEvent();
        },
        'beforerender': function()
        {
            for (i in this.opt) {
                if (i != 'store') {
                    this[i] = this.opt[i];
                }
                else {
                    this.store.loadData(this.opt.store);
                }
            }

            if (this.regex != undefined) {
                this.validator = function(value)
                {
                    return this.regex.test(value);
                };
            }
        }
    }
});

И, наконец, вот код для окна пользовательского редактора:

Ext.MultiSelectWindow = function(args)
{
    var obj = this;

    obj.args = args;

    obj.KeyValue = new Ext.data.Record.create([{
        name: 'key'
    }, {
        name: 'value'
    }]);

    obj.gridStore = new Ext.data.Store({
        data: obj.args.data,
        reader: new Ext.data.JsonReader({}, obj.KeyValue),
        autoLoad: true
    });

    obj.cm = new Ext.grid.ColumnModel([{
        id: 'key',
        header: "Key",
        dataIndex: 'key',
        editor: new Ext.form.TextField({
            allowBlank: false
        }),
        hideable: false,
        sortable: false,
        menuDisabled: true,
        css: 'font-weight: bold;'
    }, {
        id: 'value',
        header: "Value",
        dataIndex: 'value',
        editor: new Ext.form.TextField({}),
        hideable: false,
        sortable: false,
        menuDisabled: true
    }]);

    obj.gridEditor = new Ext.grid.EditorGridPanel({
        cm: obj.cm,
        height: 280,
        store: obj.gridStore,
        autoExpandColumn: 'value',

        listeners: {
            'render': function()
            {
                // set up local aliases
                obj.a = new Array();
                obj.a.grid = obj.gridEditor;
                obj.a.store = obj.a.grid.getStore();
                obj.a.sel = obj.a.grid.getSelectionModel();
            }
        },

        bbar: [{
            text: 'Add',
            cls: 'x-btn-text-icon',
            icon: '/lib/images/add.png',

            listeners: {
                'click': function()
                {
                    var kv = new obj.KeyValue({
                        key: '',
                        value: ''
                    });

                    var row = obj.a.store.data.items.length;

                    obj.a.grid.stopEditing();
                    obj.a.store.insert(row, kv);
                    obj.a.grid.startEditing(row, 0);
                }
            }
        }, {
            text: 'Delete',
            cls: 'x-btn-text-icon',
            icon: '/lib/images/delete.png',

            listeners: {
                'click': function()
                {
                    if (obj.a.sel.selection) 
                        obj.a.store.remove(obj.a.sel.selection.record);
                }
            }
        }]
    });

    obj.panelAll = new Ext.Panel({
        border: false,
        layout: 'absolute',
        items: [new Ext.Panel({
            width: 250,
            border: false,
            x: 0,
            y: 0,
            items: obj.gridEditor
        }), new Ext.Panel({
            border: false,
            x: 254,
            y: 0,
            items: [new Ext.Button({
                cls: 'x-btn-icon-side',
                icon: '/lib/images/arrow_up.png',

                listeners: {
                    'click': function()
                    {

                        if (obj.a.sel.selection) {
                            var row = obj.a.sel.selection.cell[0];
                            var rec = obj.a.store.getAt(row);

                            if (row >= 1) {
                                obj.a.store.remove(rec);
                                obj.a.store.insert(row - 1, rec);
                                obj.a.grid.startEditing(row - 1, 0);
                            }
                        }
                    }
                }
            }), new Ext.Button({
                cls: 'x-btn-icon-side',
                icon: '/lib/images/arrow_down.png',

                listeners: {
                    'click': function()
                    {
                        if (obj.a.sel.selection) {
                            var row = obj.a.sel.selection.cell[0];
                            var rec = obj.a.store.getAt(row);
                            var len = obj.a.store.data.items.length;

                            if (row < len - 1) {
                                obj.a.store.remove(rec);
                                obj.a.store.insert(row + 1, rec);
                                obj.a.grid.startEditing(row + 1, 0);
                            }
                        }
                    }
                }
            })]
        })]
    });

    obj.win = new Ext.Window({
        title: 'Repeating Value Editor',
        layout: 'fit',
        closeAction: 'hide',
        border: false,
        items: obj.panelAll,
        width: 300,
        height: 350,
        resizable: false,
        shadow: false,
        buttonAlign: 'left',

        buttons: [{
            text: 'OK',
            handler: function()
            {
                // reset the repeating field data array
                obj.args.parent.dataArray = [];

                for (r in obj.a.store.data.items) 
                    obj.args.parent.dataArray[r] = obj.a.store.data.items[r].data;

                obj.args.parent.setRawValue(attrValueToString(obj.args.parent.dataArray));
                obj.win.hide();
            }
        }, {
            text: 'Cancel',
            handler: function()
            {
                obj.win.hide();
            }
        }]
    });

    obj.show = function()
    {
        obj.win.show();
        obj.a.store.loadData(obj.args.parent.dataArray);
    }
}

Теперь для моей проблемы: все это работает нормально, за исключением 7-й строки обработчика кнопки «ОК» окна (obj.args.parent.setRawValue (attrValueToString (obj.args.parent.dataArray));).

obj - это псевдоним. obj.args.parent - псевдоним поля, открывшего окно редактора повторяющихся значений. attrValueToString () - это функция, которая принимает двумерный массив и преобразует его в строку со специальным форматированием, чтобы ее можно было отображать в удобочитаемой и понятной форме в текстовом поле TriggerField.

Данные загружаются обратно в переменную поля dataArray, и если вы снова откроете редактор, новые данные будут включены в представление. Однако мне не удается получить какое-либо значение, отображаемое в TriggerField после его создания. Я пробовал оба obj.args.parent.setValue ('abc') и obj.args.parent.setRawValue ('abc'). Не генерируется никаких исключений, но значение, отображаемое в TriggerField, не изменяется. Я даже пытался создать пользовательскую функцию для установки значения из TriggerField - что-то вроде этого:

Ext.form.customFields['repeating'] = Ext.extend(Ext.form.customFields['repeating'], {
    setFieldValue: function(value){
        this.setValue(value);
    }
});

Эта пользовательская функция работает, если она вызывается из TriggerField, но не когда она вызывается откуда-то еще (т.е. обработчик кнопки «ОК» окна редактора). Функция может быть успешно вызвана из любого места и не создает никаких исключений, однако, она только правильно устанавливает значение, если вызывается из TriggerField.

Настраиваемое поле отлично работает при создании его в качестве основного поля формы:

var sample = new Ext.form.customFields['repeating']({
    renderTo: Ext.getBody(),
    dataArray: [
        {key: 'key A', value: 'value A'}, 
        {key: 'key B', value: 'value B'}, 
        {key: 'key C', value: 'value C'}
    ]
});

Я изучил документацию по API ExtJS и выполнил все возможные поиски в Google. Я нашел несколько сообщений на форуме, которые, похоже, были от людей, имеющих схожую проблему, но они так и не получили четкого ответа.

Любая помощь в этом вопросе будет очень признательна - заранее спасибо!

1 Ответ

1 голос
/ 06 июня 2009

Я думаю, вы должны использовать Ext.override для функции-обработчика onTriggerClick, а не переопределять ее в своем суперклассе.

Вы также можете установить его сразу после создания triggerField (возможно, в обработчике события render), назначив его имени функции, т.е. trigger.onTriggerClick = somefunction.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...