如何使用Ext JsonReader返回Master Detail记录集?

时间:2010-08-13 04:44:57

标签: json extjs master-detail

假设我有发票和发票项目。我想在顶部和下方的网格中显示发票清单,我想在选定的发票中显示相应的发票项目。我有SQL和JSON部分很好。我查询发票,查询发票所有发票的发票项目(只有2个查询)。然后我将这些项目与他们的发票进行匹配。最后我将其转换为JSON。它看起来像这样。

{
  "success": true,
  "results": 2,
  "rows": [
    {
      "data": {"id": 1, "invoiceDate": "2010-01-01", "total": "101.00" },
      "invoiceItems": [
        {"id": 11, "invoiceID": 1, "item": "baseball", "subtotal": "50.00" },
        {"id": 12, "invoiceID": 1, "item": "bat", "subtotal": "51.00" }
      ]
    },
    {
      "data": {"id": 2, "invoiceDate": "2010-02-02", "total": "102.00" },
      "invoiceItems": [
        {"id": 21, "invoiceID": 2, "item": "hat", "subtotal": "52.00" },
        {"id": 22, "invoiceID": 2, "item": "baseball", "subtotal": "50.00" }
      ]
    }
  ]
}

因此,当我在顶部网格中选择发票1时,我希望看到在botton网格中显示的项目11和12。然后在选择发票2时显示21和22。每次我在发票之间切换时,我都不必返回服务器。

最后,我希望能够跟踪哪些内容发生了变化,以便我可以将数据发送回来保存。

使用Ext JS如何才能实现这一切?我还没有看到使用Ext JS的工作主要细节示例。

3 个答案:

答案 0 :(得分:1)

ExtJS当然可以做到这一点,我建议ExtJS提供帮助的工具。

但是,如果您尝试使用单个商店来包含JSON记录,则可能会遇到麻烦。我记得阅读(我搜索了一个参考,但无法找到它)你应该把商店看作一个数据库表,而不是试图在一个商店中存储父/子信息。

因此,我谦虚地建议您将发票存储在一个商店中,将发票项目存储在第二个商店中,通过一些参考(发票ID)将子发票项目链接到父发票,并使用这两个商店来支持两个不同的商店网格(或任何小部件) - 一个用于发票,另一个用于发票项目。当用户单击发票时,您的侦听器(事件处理程序)将相应地更新发票项目网格/窗口小部件。

这将是我的方法。

答案 1 :(得分:1)

在这种情况下,您需要两个读者代码如下:

var reader2 = new Ext.data.JsonReader({
    root: 'invoiceItems',
    fields: [{name: 'id', type:'int'},
             {name: 'invoiceID', type:'int'},
             {name: 'item', type:'string'},
             {name: 'subtotal': type:'float'}]
});
var reader = new Ext.data.JsonReader({
    idProperty: 'id',
    totalProperty: 'results',
    successProperty: "success",
    root: 'rows',
    fields: [
        {name: 'id', type:'int'},
        {name: 'invoiceDate', type:'date'},
        {name: 'total', type:'float'},
        {name: 'invoiceItems', convert: function(v, n){ return reader2.readRecords(n).records;} }//v: value, n: data;
    ]
});

var conn = new Ext.data.Connection({
    timeout : 120000,
    url: 'address-path-to-get-json-data',
    method : 'POST'
});
var dproxy = new Ext.data.HttpProxy(conn);

var gstore = new Ext.data.Store({
    proxy: dproxy,
    reader: reader,
    sortInfo:{field: 'id', direction: "DESC"}
});

以下是渲染网格所需的代码

var numrender = function(value, cell, rec, rowIndex, colIndex, store){
    if(value*1>0){
        return Ext.util.Format.number( value, '0,000.00');
    }else return '-';
}
var invoicedetail = function(value, cell, rec, rowIndex, colIndex, store) {
    var html = '<div class="itemdetail">{0} - {1} - {2} - {3}</div>';
    var re = '';
    Ext.each(value,function(item,index){
        re += String.format(html,item.get('id'),item.get('invoiceID'),item.get('item'),item.get('subtotal'));
    });
    return re;
}
var cm = [
    new Ext.grid.RowNumberer({header:"No.", width: 30}),
    {header: "ID", align: 'left',sortable:true, width: 40, dataIndex: 'id'},
    {header: "Invoice Date", align: 'left',sortable:true, width: 40, dataIndex: 'invoiceDate'},
    {header: "Total", align: 'right', width: 30, dataIndex: 'total', renderer: numrender},
    {header: "Invoice Items", align: 'left',sortable:false, id:'col_detail', width: 100, dataIndex: 'invoiceItems', renderer: invoicedetail}
];

var grid = new Ext.grid.GridPanel({
    id:'invoices',
    store: gstore,
    columns: cm,
    enableHdMenu: false,
    loadMask: {msg:'Loading Invoices ...'},
    enableColumnResize:false,
    stripeRows: true,
    viewConfig: { autoFill: true },
    columnLines : true,
    autoExpandColumn: 'col_detail',
    renderTo:'grid-wrapper'
});
gstore.load();

或者你可能有兴趣看看这个treegrid:

http://www.max-bazhenov.com/dev/ux.maximgb.tg/index.php

答案 2 :(得分:0)

这当然是可能的,但是你并没有真正映射子对象,而只是期望它们在那里......

考虑这个测试用例(将其粘贴到FireBug中,你应该看到结果......)


var store = new Ext.data.JsonStore({
    data: {
success: true, result: [
{
test: {prop1: 1, prop2: 2}
}]
},
    root: 'result',
    fields: ['test']
});

console.log(store.getRange()[0].data.test.prop1); // prints "1"

在您的实例中,您可以在行选择事件中执行类似的操作...


//assume "this" = your panel containing your Grid (at position 0) and another Grid (at position 1)
var selectedRowRecord = this.get(0).getSelectionModel().getSelected();

var invoiceItemsStore = this.get(1).getStore();
invoiceItemsStore.removeAll();
invoiceItemsStore.loadData(selectedRowRecord.data.invoiceItems);

希望这会有所帮助。 斯图尔特