ExtJs и вложенные модели - PullRequest
       5

ExtJs и вложенные модели

3 голосов
/ 27 марта 2012

Допустим, у меня есть модель под названием Vehicle

Ext.define('AM.model.Vehicle', {
    extend: 'Ext.data.Model',
    fields: [
        {name: 'brandId',  type: 'int'}, 
        {name: 'brandName',  type: 'string'},
        {name: 'modelId',  type: 'int'}, 
        {name: 'modelName',  type: 'string'},
        {name: 'yearOfRelease',  type: 'int'}
    ]

});

Как видите, модель автомобиля имеет поля "brandId", "brandName" и т. Д. Например, я хочу отредактировать экземпляр этой модели. Я создаю форму редактирования, в которой выпадающий список связан с полем «brandId». Затем я сохраняю значения формы в экземпляре модели с этим

values = form.getValues();
record.set(values);

Все работает нормально, но есть проблема со всеми полями, которые представляют некоторые внешние модели: обновляются только идентификаторы, а все остальные поля, которые зависят от идентификатора, остаются прежними.

На обычном языке ООП (например, Java) я бы создал класс CarBrand и поместите экземпляр этого класса в класс Vehicle. В ExtJs 4 у ​​них есть отношение hasMany, но нет hasOne.

Каков наилучший подход в ExtJS 4 для таких вложенных моделей?

Ответы [ 2 ]

10 голосов
/ 27 марта 2012

4.0. * Не поддерживает отношение hasOne. 4.1 предназначен для поддержки.

для 4.0.7 У меня есть следующее переопределение.

Ext.define('HOD.overrides.Form', {}, function() {

/*
 * Implementing a nested setValues for forms with
 * arrays in them.
 */
Ext.override(Ext.form.Basic, {
    setValues: function(values, arrayField) {
        var me = this;

        function setVal(fieldId, val) {
            if (arrayField) {
                fieldId = arrayField + '.' + fieldId;
            }
            var field = me.findField(fieldId);
            if (field) {
                field.setValue(val);
                if (me.trackResetOnLoad) {
                    field.resetOriginalValue();
                }
            } else if(Ext.isObject(val)) {
                me.setValues(val, fieldId);
            }
        }

        if (Ext.isArray(values)) {
            // array of objects
            Ext.each(values, function(val) {
                setVal(val.id, val.value);
            });
        } else {
            // object hash
            Ext.iterate(values, setVal);
        }
        return this;
    },
    /**
     * Persists the values in this form into the passed {@link Ext.data.Model} object in a beginEdit/endEdit block.
     * @param {Ext.data.Model} record The record to edit
     * @return {Ext.form.Basic} this
     */
    updateRecord: function(record) {
        var values = this.getFieldValues(),
        name,
        obj = {};

        function populateObj(record, values) {
            var obj = {},
            name;

            record.fields.each(function(field) {
                name = field.name;
                if (field.model) {
                    var nestedValues = {};
                    var hasValues = false;
                    for(var v in values) {
                        if (v.indexOf('.') > 0) {
                            var parent = v.substr(0, v.indexOf('.'));
                            if (parent == field.name) {
                                var key = v.substr(v.indexOf('.') + 1);
                                nestedValues[key] = values[v];
                                hasValues = true;
                            }
                        }
                    }
                    if (hasValues) {
                        obj[name] = populateObj(Ext.create(field.model), nestedValues);
                    }
                } else if (name in values) {
                    obj[name] = values[name];
                }
            });
            return obj;
        }

        obj = populateObj(record, values);

        record.beginEdit();
        record.set(obj);
        record.endEdit();

        return this;
    }
});

Что мне позволяет делать, так это в своих формах я создаю их с такими именами.

// Contact details
{
    xtype: 'fieldcontainer',
    defaultType: 'textfield',
    layout: 'anchor',
    fieldDefaults: {
        anchor: '80%',
        allowBlank: true
    },
    items: [

    {
        xtype: 'textfield',
        name: 'homePhone',
        fieldLabel: 'Home phone number'
    },
    {
        xtype: 'textfield',
        name: 'mobilePhone',
        fieldLabel: 'Mobile phone number'
    }]
},
{
    xtype: 'fieldcontainer',
    defaultType: 'textfield',
    layout: 'anchor',
    fieldDefaults: {
        anchor: '80%',
        allowBlank: true
    },
    items: [
    {
        name: 'address.id',
        xtype: 'hidden'
    },
    {
        name: 'address.building',
        fieldLabel: 'Building'
    },
    {
        name: 'address.street',
        fieldLabel: 'Street'
    },
    {
        name: 'address.city',
        fieldLabel: 'City'
    },
    {
        name: 'address.county',
        fieldLabel: 'County'
    },
    {
        name: 'address.postcode',
        fieldLabel: 'Postcode'
    },
    {
        name: 'address.country',
        fieldLabel: 'Country'
    }
    ]
},
]

Обратите внимание. в поле имени, которое позволяет переопределенным формам setValues ​​и updateRecord знать, что необходимо сопоставить эти значения с новой моделью, которая определена в модели следующим образом.

Ext.define('HOD.model.Employee', {
    extend: 'Ext.data.Model',
    fields: [
        // Person Class
        // Auto
        'id',
        'name',
        'homePhone',
        'mobilePhone',
        {model: 'HOD.model.Address', name: 'address'}, //Address
        {model: 'HOD.model.Contact', name: 'iceInformation'} //Person
    ]
});

Ext.define('HOD.model.Address', {
    extend: 'Ext.data.Model',
    fields: [
        'building',
        'street',
        'city',
        'county',
        'postcode',
        'country'
    ],
    belongsTo: 'Employee'
});
2 голосов
/ 27 марта 2012

Вложенных моделей нет, однако из вашего примера непонятно, почему вы это делаете.Зачем вам нужно сохранять и идентификатор, и имена в записи автомобиля, если у вас уже есть эта связь в какой-то другой базе данных (я предполагаю, что у вас есть что-то вроде словаря брендов, где вы храните все пары идентификатор / имя?).

Обновление: я бы сделал следующее:

  • Сохраняйте только brand_id в записи транспортного средства.
  • Когда у вас есть форма, представьте комбинированный список со значениями из хранилища словарей и обновите brand_id
  • Когда у вас есть сетка - определите пользовательскую функцию 'рендерер' для столбца и получите название бренда из магазина словарей по номеру brand_id

Вот пример кода для такого столбца:

{ text: 'Brand Name', dataIndex: 'brand_id', 
    renderer: function(value) {
       var rec = Ext.getStore('BrandDict').getById(value);
       return rec ? rec.get('name') : '';
}
...