2013-04-15 17 views
6

詳細

私は請求書情報を表示するためのグリッドを持っています。グリッドはインボイスストアを使用して、インボイスストアはインボイスモデルを、インボイスモデルはプライマリキーが 'id'、forenキーが 'invoice_status_id'のInvoiceStatusモデルとの "1つの関連付け"を使用します。EXT JS 4グリッド表示値をレンダリングするためのモデルアソシエーションを使用

問題

私は、請求書、グリッドの「ステータス」列の表示値がinvoice_status_idの挿入に関連するモデルの名前」を使用するようするかどうかはわかりません。これを行うためにレンダラーを作成する必要があることは分かっていますが、まだヌル値が得られます。請求書とInvoiceStatusの両方に正しい値が入力されています。

ステータス列は、レンダリング

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

請求書ストア

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ストア

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)]); 
    } 
}); 

請求書モデル

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モデル

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

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

請求書グリッド

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

私はこれを私の列レンダラーstore.getAt(rowIndex).getStatus()。get( 'name');で試してみました。 –

答えて

10

コールバック関数を使用してアソシエーション検索を実行することができましたが、店舗からの検索を簡単に行うことがはるかに簡単でした。

ステップ1

私はInvoiceStatusストアからとInvoiceStatusモデル上にプロキシを移動し、InvoiceStatusストアの自動ロードを作りました。

ステップ2

私はそうのようなInvoiceStatusストアから表示名を検索するStatus列の描画方法を変更しました。

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

これは多くのsimpelerソリューションであることが判明しました。

+0

すてきな回避策!ありがとう。 Obs:エラーを避けるために、nullをチェックすることを忘れないでください。if(value && value> 0){/*...*/} –

3

あなたはInvoiceStatusカイにbelongsToの関連付けを設定する必要があるように見えますモデル。ある方向への関連付けの定義は、自動的に別の方向への関連付けを作成すると考えられますが、そうでない場合は、親と子の両方で関連付けを定義する必要があります。 Why isn't my ExtJS Store Association Working

+0

ジェームズありがとう、これは答えの一部だった。実際の問題は、私の関連ストアがjsonストアであったため、それをロードする必要があったために、そこから値を取り除くことができるということでした。これは、レンダリング関数の一部としてコールバックメソッドを必要としました。これは、面倒なロードプロセスのために作成されたもので、ルックアップ値をレンダリングする簡単な方法を見つけることができなくなってしまいました。私の答えを見てください。 –

3

あなたのhasOneのは、次のようにする必要があります:

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

ExtJSの4.2.2のための次のパッチは、あなたが任意の追加のレンダラなしdataIndex: 'status.name'を設定できます。グリッドはすべてOKと表示されますが、並べ替えは機能しません。

このソリューションは、非同期(遅延)状態の負荷では機能しません。

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; 
}; 
関連する問題