2013-04-15 25 views
6

Chi tiết

Tôi có lưới được sử dụng để hiển thị thông tin hóa đơn. Lưới được điền bằng cách sử dụng cửa hàng Invoice, cửa hàng Invoice sử dụng mô hình hóa đơn, mô hình hóa đơn có một liên kết "có một" với mô hình InvoiceStatus với khóa chính của 'id' và khóa chính của 'invoice_status_id'.EXT JS 4 sử dụng liên kết mô hình để hiển thị giá trị hiển thị lưới

Vấn đề

Tôi không chắc chắn làm thế nào để làm cho giá trị hiển thị của 'Trạng thái' cột Invoice Lưới của sử dụng các mô hình liên quan 'tên' chèn của invoice_status_id. Tôi biết tôi cần phải tạo ra một renderer để làm điều này tuy nhiên tôi vẫn nhận được một giá trị null. Cả Invoice và InvoiceStatus stors đều có các giá trị chính xác.

Cột trạng thái Render

renderer: function(value, metaData, record, rowIndex, colIndex, store, view) { 
    return record.getStatus().get('name'); 
}, 

Invoice cửa hàng

Ext.define('MyApp.store.Invoice', { 
    extend: 'Ext.data.Store', 

    requires: [ 
     'MyApp.model.InvoiceModel' 
    ], 

    constructor: function(cfg) { 
     var me = this; 
     cfg = cfg || {}; 
     me.callParent([Ext.apply({ 
      autoLoad: true, 
      autoSync: true, 
      model: 'MyApp.model.InvoiceModel', 
      remoteSort: true, 
      storeId: 'StoreInvoce', 
      proxy: { 
       type: 'rest', 
       url: '/api/invoice', 
       reader: { 
        type: 'json', 
        root: 'data' 
       } 
      } 
     }, cfg)]); 
    } 
}); 

InvoiceStatus cửa hàng

Ext.define('MyApp.store.InvoiceStatus', { 
    extend: 'Ext.data.Store', 
    alias: 'store.InvoiceStatus', 

    requires: [ 
     'MyApp.model.InvoiceStatus' 
    ], 

    constructor: function(cfg) { 
     var me = this; 
     cfg = cfg || {}; 
     me.callParent([Ext.apply({ 
      autoLoad: true, 
      autoSync: true, 
      model: 'MyApp.model.InvoiceStatus', 
      remoteSort: true, 
      storeId: 'MyJsonStore1', 
      proxy: { 
       type: 'rest', 
       url: '/api/invoice_status', 
       reader: { 
        type: 'json', 
        root: 'data' 
       } 
      } 
     }, cfg)]); 
    } 
}); 

Invoice Mẫu

Ext.define('MyApp.model.InvoiceModel', { 
    extend: 'Ext.data.Model', 

    uses: [ 
     'MyApp.model.InvoiceStatus' 
    ], 

    fields: [ 
     { 
      mapping: 'id', 
      name: 'id', 
      type: 'int' 
     }, 
     { 
      mapping: 'client_id', 
      name: 'client_id', 
      type: 'int' 
     }, 
     { 
      mapping: 'client_name', 
      name: 'client_name', 
      type: 'string' 
     }, 
     { 
      dateFormat: 'Y-m-d', 
      dateReadFormat: '', 
      mapping: 'issue_date', 
      name: 'issue_date', 
      sortType: 'asDate', 
      type: 'date' 
     }, 
     { 
      dateFormat: 'Y-m-d', 
      mapping: 'due_date', 
      name: 'due_date', 
      sortType: 'asDate', 
      type: 'date' 
     }, 
     { 
      mapping: 'payment_date', 
      name: 'payment_date', 
      sortType: 'asDate', 
      type: 'date', 
      useNull: true 
     }, 
     { 
      name: 'amount' 
     }, 
     { 
      mapping: 'invoice_status_id', 
      name: 'invoice_status_id', 
      sortType: 'asInt', 
      type: 'int' 
     } 
    ], 

    hasOne: { 
     model: 'MyApp.model.InvoiceStatus', 
     foreignKey: 'invoice_status_id', 
     getterName: 'getStatus' 
    } 
}); 

InvoiceStatus Mẫu

Ext.define('MyApp.model.InvoiceStatus', { 
    extend: 'Ext.data.Model', 

    fields: [ 
     { 
      mapping: 'id', 
      name: 'id', 
      type: 'int' 
     }, 
     { 
      mapping: 'name', 
      name: 'name', 
      type: 'string' 
     } 
    ] 
}); 

Invoice Lưới

Ext.define('MyApp.view.ApplicationViewport', { 
    extend: 'Ext.container.Viewport', 

    requires: [ 
     'MyApp.view.ClearTriggerField' 
    ], 

    layout: { 
     type: 'border' 
    }, 

    initComponent: function() { 
     var me = this; 

     Ext.applyIf(me, { 
      items: [ 
       { 
        xtype: 'header', 
        region: 'north', 
        height: 100, 
        items: [ 
         { 
          xtype: 'image', 
          height: 100, 
          width: 250, 
          alt: 'Logo', 
          src: 'images/logo.gif', 
          title: 'Logo' 
         } 
        ] 
       }, 
       { 
        xtype: 'container', 
        region: 'center', 
        layout: { 
         type: 'card' 
        }, 
        items: [ 
         { 
          xtype: 'container', 
          width: 150, 
          layout: { 
           type: 'border' 
          }, 
          items: [ 
           { 
            xtype: 'gridpanel', 
            collapseMode: 'mini', 
            region: 'west', 
            split: true, 
            autoRender: false, 
            maxWidth: 300, 
            width: 250, 
            bodyBorder: false, 
            animCollapse: false, 
            collapsed: false, 
            collapsible: true, 
            hideCollapseTool: true, 
            overlapHeader: false, 
            titleCollapse: true, 
            allowDeselect: true, 
            columnLines: false, 
            forceFit: true, 
            store: 'ClientDataStor', 
            dockedItems: [ 
             { 
              xtype: 'toolbar', 
              dock: 'top', 
              items: [ 
               { 
                xtype: 'cleartrigger' 
               }, 
               { 
                xtype: 'tbfill' 
               }, 
               { 
                xtype: 'button', 
                icon: '/images/settings.png' 
               } 
              ] 
             } 
            ], 
            columns: [ 
             { 
              xtype: 'templatecolumn', 
              tpl: [ 
               '<img class="pull-left client-menu-image" src="/images/{type}.png"><div class="client-menu-name">{name}</div><div class="client-menu-type">{type}</div>' 
              ], 
              dataIndex: 'id', 
              text: 'Client' 
             } 
            ], 
            selModel: Ext.create('Ext.selection.RowModel', { 

            }), 
            plugins: [ 
             Ext.create('Ext.grid.plugin.BufferedRenderer', { 

             }) 
            ] 
           }, 
           { 
            xtype: 'gridpanel', 
            region: 'center', 
            title: 'Invoices', 
            titleCollapse: false, 
            forceFit: true, 
            store: 'Invoice', 
            columns: [ 
             { 
              xtype: 'numbercolumn', 
              maxWidth: 120, 
              minWidth: 50, 
              dataIndex: 'id', 
              groupable: false, 
              lockable: true, 
              text: 'ID', 
              tooltip: 'Invoice ID', 
              format: '0' 
             }, 
             { 
              xtype: 'numbercolumn', 
              hidden: true, 
              maxWidth: 120, 
              minWidth: 50, 
              dataIndex: 'client_id', 
              groupable: true, 
              text: 'Client ID', 
              format: '0' 
             }, 
             { 
              xtype: 'gridcolumn', 
              renderer: function(value, metaData, record, rowIndex, colIndex, store, view) { 
               return record.getStatus().get('name'); 
              }, 
              maxWidth: 200, 
              minWidth: 100, 
              dataIndex: 'invoice_status_id', 
              text: 'Status' 
             }, 
             { 
              xtype: 'datecolumn', 
              maxWidth: 200, 
              minWidth: 100, 
              dataIndex: 'issue_date', 
              text: 'Issue Date', 
              format: 'd M Y' 
             }, 
             { 
              xtype: 'datecolumn', 
              maxWidth: 200, 
              minWidth: 100, 
              dataIndex: 'due_date', 
              text: 'Due Date', 
              format: 'd M Y' 
             }, 
             { 
              xtype: 'datecolumn', 
              maxWidth: 200, 
              minWidth: 100, 
              dataIndex: 'payment_date', 
              text: 'Payment Date', 
              format: 'd M Y' 
             }, 
             { 
              xtype: 'templatecolumn', 
              summaryType: 'sum', 
              maxWidth: 150, 
              minWidth: 50, 
              tpl: [ 
               '${amount}' 
              ], 
              defaultWidth: 80, 
              dataIndex: 'amount', 
              groupable: true, 
              text: 'Amount' 
             } 
            ], 
            features: [ 
             { 
              ftype: 'grouping' 
             } 
            ] 
           } 
          ] 
         } 
        ] 
       } 
      ] 
     }); 

     me.callParent(arguments); 
    } 

}); 
+0

Tôi cũng đã thử điều này trong cửa sổ trình kết xuất cột của tôi.getAt (rowIndex) .getStatus(). Get ('name'); –

Trả lời

10

Tôi quản lý để tìm kiếm liên kết hoạt động bằng cách sử dụng chức năng gọi lại nhưng thấy dễ dàng hơn khi thực hiện tra cứu từ cửa hàng.

Bước Một

Tôi di chuyển các Proxy từ các cửa hàng InvoiceStatus và vào mô hình InvoiceStatus và làm cho các cửa hàng autoload InvoiceStatus.

Bước Hai

tôi đã thay đổi render phương pháp cột Trạng thái để tra cứu tên hiển thị từ các cửa hàng InvoiceStatus như vậy.

renderer: function(value, metaData, record, rowIndex, colIndex, store, view) { 
    var store = Ext.data.StoreManager.lookup('InvoiceStatus'); 
    return store.getById(value).get('name'); 
}, 

Điều này được chứng minh là giải pháp nhiều simpeler.

+0

giải pháp tuyệt vời! cảm ơn. Quan sát: hãy nhớ kiểm tra các giá trị rỗng để tránh lỗi, ví dụ: if (value && value> 0) {/*...*/} –

3

Có vẻ như bạn cần phải thiết lập các hiệp hội belongsTo trên InvoiceStatus chi mô hình ld. Bạn sẽ nghĩ rằng việc xác định liên kết theo một hướng sẽ tự động tạo liên kết theo một hướng khác, nhưng dường như điều đó không đúng và bạn phải xác định liên kết trên cả cha và mẹ. Xem tại đây để được giải thích chi tiết hơn: Why isn't my ExtJS Store Association Working

+0

Cảm ơn James, đây là một phần của câu trả lời. Vấn đề thực sự là cửa hàng liên quan của tôi là một cửa hàng json và nó cần thiết để tải trước khi giá trị có thể được thu hút từ nó. Điều này đòi hỏi một phương thức gọi lại như là một phần của hàm render, điều này được thực hiện cho một quá trình tải lộn xộn và tôi đã kết thúc việc tìm kiếm một phương thức hiển thị các giá trị tra cứu dễ dàng hơn. Xem câu trả lời của tôi. –

3

hasOne của bạn nên được như thế này:

hasOne: { 
    name:   'status', 
    instanceName: 'status', 
    associationKey: 'status', 
    model:   'MyApp.model.InvoiceStatus', 
    foreignKey:  'invoice_status_id', 
    getterName:  'getStatus', 
    setterName:  'setStatus' 
} 

Các miếng vá sau cho ExtJS 4.2.2 sẽ cho phép bạn đặt dataIndex: 'status.name' mà không cần bất kỳ kết xuất đồ họa bổ sung. Lưới sẽ hiển thị mọi thứ OK nhưng sắp xếp sẽ không hoạt động.

Giải pháp này không hoạt động với tải trạng thái không đồng bộ (lười).

Ext.view.Table.prototype.renderCell = function(column, record, recordIndex, rowIndex, columnIndex, out) { 
    var me = this, 
     selModel = me.selModel, 
     cellValues = me.cellValues, 
     classes = cellValues.classes, 
     // fieldValue = record.data[column.dataIndex]; // patched 
     fieldValue = null, 
     cellTpl = me.cellTpl, 
     fullIndex, value, clsInsertPoint; 

    // Patch start 
    if (column.dataIndex && column.dataIndex.indexOf('.') > 0) { 
     var associationParts = column.dataIndex.split('.'), 
      v = record; 

     for (var i = 0; i < associationParts.length-1; i++) { 
      v = v['get' + associationParts[i].charAt(0).toUpperCase() + associationParts[i].slice(1)](); 
     } 
     fieldValue = v.get(associationParts[associationParts.length-1]); 
    } 
    else { 
     fieldValue = record.data[column.dataIndex]; 
    } 
    // Patch end 

    cellValues.record = record; 
    cellValues.column = column; 
    cellValues.recordIndex = recordIndex; 
    cellValues.rowIndex = rowIndex; 
    cellValues.columnIndex = columnIndex; 
    cellValues.cellIndex = columnIndex; 
    cellValues.align = column.align; 
    cellValues.tdCls = column.tdCls; 
    cellValues.innerCls = column.innerCls; 
    cellValues.style = cellValues.tdAttr = ""; 
    cellValues.unselectableAttr = me.enableTextSelection ? '' : 'unselectable="on"'; 

    if (column.renderer && column.renderer.call) { 
     fullIndex = me.ownerCt.columnManager.getHeaderIndex(column); 
     value = column.renderer.call(column.scope || me.ownerCt, fieldValue, cellValues, record, recordIndex, fullIndex, me.dataSource, me); 
     if (cellValues.css) { 
      // This warning attribute is used by the compat layer 
      // TODO: remove when compat layer becomes deprecated 
      record.cssWarning = true; 
      cellValues.tdCls += ' ' + cellValues.css; 
      delete cellValues.css; 
     } 
    } else { 
     value = fieldValue; 
    } 
    cellValues.value = (value == null || value === '') ? '&#160;' : value; 

    // Calculate classes to add to cell 
    classes[1] = column.getCellId(); 

    // On IE8, array[len] = 'foo' is twice as fast as array.push('foo') 
    // So keep an insertion point and use assignment to help IE! 
    clsInsertPoint = 2; 

    if (column.tdCls) { 
     classes[clsInsertPoint++] = column.tdCls; 
    } 
    if (me.markDirty && record.isModified(column.dataIndex)) { 
     classes[clsInsertPoint++] = me.dirtyCls; 
    } 
    if (column.isFirstVisible) { 
     classes[clsInsertPoint++] = me.firstCls; 
    } 
    if (column.isLastVisible) { 
     classes[clsInsertPoint++] = me.lastCls; 
    } 
    if (!me.enableTextSelection) { 
     classes[clsInsertPoint++] = me.unselectableCls; 
    } 
    if (cellValues.tdCls) { 
     classes[clsInsertPoint++] = cellValues.tdCls; 
    } 
    if (selModel && selModel.isCellModel && selModel.isCellSelected(me, recordIndex, columnIndex)) { 
     classes[clsInsertPoint++] = (me.selectedCellCls); 
    } 

    // Chop back array to only what we've set 
    classes.length = clsInsertPoint; 

    cellValues.tdCls = classes.join(' '); 

    cellTpl.applyOut(cellValues, out); 

    // Dereference objects since cellValues is a persistent var in the XTemplate's scope chain 
     cellValues.column = null; 
};