2012-03-27 111 views
3

比方说,我有一个名为车载ExtJS的和嵌套模型

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”,“名优产品”等 例如,我想编辑模式这个模型的一个实例。 我创建了一个编辑窗体,它具有链接到'brandId'字段的组合框。 后来我表单值保存到一个模型实例与此

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

这一切工作正常,但有一个问题,所有代表的一些外部模型的字段: 唯一的ID被更新,而其他所有领域,依靠id保持不变。

在常规OOP语言(Java为例),我想创建一个类CarBrand ,并把这个类的一个实例Vehicle类里面。 在ExtJs 4中他们有很多关系,但没有hasOne。

对于这样的嵌套模型,ExtJS 4中的最佳方法是什么?

回答

10

4.0 *不支持hasOne关系。 4.1是为了支持它。

for 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' 
}); 
+0

这是一个实实在在的解决方案。还有一个类似的线程关于一个2许多协会在这里:http://stackoverflow.com/questions/9871440/extjs-store-one2many-and-update-process-howto – dbrin 2012-03-27 17:20:09

2

没有嵌套模型,但是从您的示例中不清楚您为什么要这样做。为什么你需要在汽车记录中保存身份证和姓名,如果你已经在其他数据库中有这种关系(我假设你有类似品牌字典的地方,你保留所有的身份证/姓名?)。

更新:我会做到以下几点:

  • 只保留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') : ''; 
} 
+0

你是对的,我有品牌词典。我需要更新名称才能在网格中显示正确的值。我不喜欢这种方法 - 我必须将所有字段从品牌模型复制到车辆模型。在我的例子中只有一个额外的字段名称,但可以有更多... – mik 2012-03-27 14:56:11

+0

不,你没有。如果您只需要在网格中显示它们 - 使用自定义渲染器,但仍然让它们编辑相同的组合框字段。 – sha 2012-03-27 15:02:59

+0

我对渲染器不太了解。你可以解释吗? – mik 2012-03-27 15:21:11