Ag-grid 视口:无法读取未定义的 属性 'bind'
Ag-grid viewport: cannot read property 'bind' of undefined
我正在复制 ag-grid 视口示例,将其放入表示 table 而不是匿名函数的 object 中。我不明白为什么它在尝试连接到模拟服务器时给我标题中的错误,因为它是完全相同的代码。
这是似乎不起作用的代码:
function ViewportDatasource(mockServer) {
this.mockServer = mockServer;
this.connectionId = this.mockServer.connect(this.eventListener.bind(this));
}
ViewportDatasource.prototype.eventListener = function (event) {
switch (event.eventType) {
case 'rowCountChanged':
this.onRowCountChanged(event);
break;
case 'rowData':
this.onRowData(event);
break;
case 'dataUpdated':
this.onDataUpdated(event);
break;
}
};
这是全部object:
function WatcherTable($rootScope,$scope, $http) {
this.FIELD_KEY_ID = "id";
this.FIELD_KEY_ISSUER_SHORT_DESC= "isd";
this.FIELD_KEY_ISSUER = "iss";
this.FIELD_KEY_CUSIP = "cus";
this.FIELD_KEY_ISIN = "isin";
this.FIELD_KEY_BOARD_LABEL = "lbl";
this.FIELD_KEY_IND_SECT_LABEL = "isl";
this.FIELD_KEY_CURR="cur"
this.FIELD_KEY_BEST_BID_SIZE = "bBidSz";
this.FIELD_KEY_BEST_BID_PRICE = "bBidPrc";
this.FIELD_KEY_BEST_ASK_PRICE = "bAskPrc";
this.FIELD_KEY_BEST_ASK_SIZE = "bAskSz";
this.FIELD_KEY_BEST_BID_SPREAD = "bBidSpd";
this.FIELD_KEY_BEST_ASK_SPREAD = "bAskSpd";
this.FIELD_KEY_ORDER_BID_SIZE = "oBidSz";
this.FIELD_KEY_ORDER_BID_PRICE = "oBidPrc";
this.FIELD_KEY_ORDER_ASK_PRICE = "oAskPrc";
this.FIELD_KEY_ORDER_ASK_SIZE = "oAskSz";
this.FIELD_KEY_ORDER_BID_SPREAD = "oBidSpd";
this.FIELD_KEY_ORDER_ASK_SPREAD = "oAskSpd";
this.headerMyOrder="ORDER";
this.headerMyBidOrder="BID ORDER";
this.headerMyAskOrder="ASK ORDER";
this.cols = [{
headerName : "Security Info",
marryChildren : true,
children : [{
headerName : "Issuer Short Desc.",
field : this.FIELD_KEY_ISSUER_SHORT_DESC,
//width : 0,
//hide : true
},
{
headerName : "Industry Sector Label",
field : this.FIELD_KEY_IND_SECT_LABEL,
//width : 80,
filter: 'set',
filterParams: { values: ['Advertising', 'Aerospace/Defense', 'Agriculture', 'Airlines', 'Apparel', 'Auto Manufacturers', 'Auto Parts&Equipment', 'Banks', 'Basic Materials', 'Beverages', 'Biotechnology', 'Building Materials', 'Chemicals', 'Coal', 'Commercial Services', 'Communications', 'Computers', 'Consumer, Cyclical', 'Consumer, Non-cyclical', 'Cosmetics/Personal Care', 'Distribution/Wholesale', 'Diversified', 'Electrical Compo&Equip', 'Electronics', 'Energy', 'Energy-Alternate Sources', 'Engineering&Construction', 'Entertainment', 'Machinery-Constr&Mining', 'Household Products/WaresIndustrial', 'Insurance', 'Internet', 'Investment Companies', 'Iron/Steel', 'Kangaroos', 'Leisure Time', 'Lodging', 'Machinery-Constr&Mining', 'Machinery-Diversified', 'Media', 'Metal Fabricate/Hardware', 'Mining', 'Miscellaneous Manufactur', 'Multi-National', 'Office Furnishings', 'Office/Business ', 'Oil&Gas', 'Oil&Gas Services', 'Packaging&Containers', 'Pharmaceuticals', 'Pipelines', 'Real Estate', 'Regional(state/provnc)', 'REITS', 'Retail', 'Savings&Loans'],
newRowsAction: 'keep'},
},
{
headerName : "Board Label",
field : this.FIELD_KEY_BOARD_LABEL,
//width : 80,
filter: 'text',
filterParams: { apply: true }
}, {
headerName : "CUSIP",
field : this.FIELD_KEY_CUSIP,
//width : 150,
//suppressFilter: true
},
{
headerName : "ISIN",
field : this.FIELD_KEY_ISIN,
//width : 150,
//suppressFilter: true
},
{
headerName : "Currency",
field : this.FIELD_KEY_CURR,
//width : 150,
//suppressFilter: true
}
]},
{
headerName : "Best",
marryChildren : true,
children : [ {
headerName : "Bid Size",
pinned: 'right',
field : this.FIELD_KEY_BEST_BID_SIZE,
cellStyle: {'border-left': '1px solid #E82043', 'color':'#E82043', 'font-weight':'bold', 'text-align':'right'},
cellRenderer: BidRenderer,
filter:'number',
//width : 125,
//suppressFilter: true
}, {
headerName : "Bid Price",
pinned: 'right',
field : this.FIELD_KEY_BEST_BID_PRICE,
cellStyle: {'border-right': '1px solid #E82043', 'color':'#E82043', 'font-weight':'bold', 'text-align':'right'},
//cellRenderer: 'animateShowChange',
cellFormatter: numberFormatter,
cellRenderer: BidRenderer,
width : 125,
filter:'number',
//suppressFilter: true
},
{
headerName : "Ask Price",
pinned: 'right',
field : this.FIELD_KEY_BEST_ASK_PRICE,
//cellRenderer: 'animateShowChange',
cellFormatter: numberFormatter,
cellRenderer: AskRenderer,
cellStyle: {'color':'#19B092', 'font-weight':'bold', 'text-align':'right'},
filter:'number',
//width : 125,
//suppressFilter: true
},
{
headerName : "Ask Size",
pinned: 'right',
field : this.FIELD_KEY_BEST_ASK_SIZE,
cellStyle: {'border-right': '1px solid #19B092', 'color':'#19B092', 'font-weight':'bold', 'text-align':'right'},
cellRenderer: AskRenderer,
filter:'number',
//width : 125,
//suppressFilter: true
} ]
} ];
//definizione della tabella//// rowModelType: 'virtual', rowModelType: 'pagination',
this.table = {
showPrice: true,
showSpread: true,
orderSize: 0,
orderFilter: '',
enableServerSideFilter: true,
enableServerSideSorting: true,
sortingOrder: ['desc','asc',null],
enableColResize : true,
debug : true,
rowSelection : 'multiple',
rowDeselection : true,
columnDefs : this.cols,
rowModelType : 'viewport',
headerHeight: 20,
rowHeight: 20,
viewportRowModelPageSize:30,
viewportRowModelBufferSize: 15,
suppressColumnVirtualisation: true,
suppressMenuColumnPanel: true,
onCellDoubleClicked: WatcherTable.prototype.onCellDoubleClicked.bind(this,$rootScope),
getContextMenuItems: WatcherTable.prototype.getContextMenuItems.bind(this,$rootScope),
getMainMenuItems: WatcherTable.prototype.getMainMenuItems.bind(this, $rootScope),
getRowNodeId: function (data) {
// the code is unique, so perfect for the id
return data.isin;
},
onGridReady:setRowData($http)
};
function numberFormatter(params) {
if (typeof params.value === 'number') {
return params.value.toFixed(4);
} else {
return params.value;
}
}
function BidRenderer () {}
BidRenderer.prototype.init = function(params) {
// create the cell
this.eGui = document.createElement('div');
this.eGui.innerHTML = '<div></div>';
// set value into cell
this.eValue = this.eGui.querySelectorAll('div')[0];
this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;
};
// gets called once when grid ready to insert the element
BidRenderer.prototype.getGui = function() {
return this.eGui;
};
// gets called whenever the user gets the cell to refresh
BidRenderer.prototype.refresh = function(params) {
// set value into cell again
this.eGui.innerHTML = '<div class="bid"></div>';
this.eValue = this.eGui.querySelectorAll('div')[0];
this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;
};
function AskRenderer () {}
AskRenderer.prototype.init = function(params) {
// create the cell
this.eGui = document.createElement('div');
this.eGui.innerHTML = '<div></div>';
// set value into cell
this.eValue = this.eGui.querySelectorAll('div')[0];
this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;
};
// gets called once when grid ready to insert the element
AskRenderer.prototype.getGui = function() {
return this.eGui;
};
// gets called whenever the user gets the cell to refresh
AskRenderer.prototype.refresh = function(params) {
// set value into cell again
this.eGui.innerHTML = '<div class="ask"></div>';
this.eValue = this.eGui.querySelectorAll('div')[0];
this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;
};
// client code (ie your code) will call this constructor, pass in whatever you need for the
// viewport to do it's job
function ViewportDatasource(mockServer) {
this.mockServer = mockServer;
this.connectionId = this.mockServer.connect(this.eventListener.bind(this));
}
// gets called by the grid, tells us what rows the grid is displaying, so time for
// us to tell the server to give us the rows for that displayed range
ViewportDatasource.prototype.setViewportRange = function (firstRow, lastRow) {
this.mockServer.setViewportRange(this.connectionId, firstRow, lastRow);
};
// gets called by the grid, provides us with the callbacks we need
ViewportDatasource.prototype.init = function (params) {
this.params = params;
};
// gets called by grid, when grid is destroyed or this datasource is swapped out for another one
ViewportDatasource.prototype.destroy = function () {
this.mockServer.disconnect(this.connectionId);
};
// manages events back from the server
ViewportDatasource.prototype.eventListener = function (event) {
switch (event.eventType) {
case 'rowCountChanged':
this.onRowCountChanged(event);
break;
case 'rowData':
this.onRowData(event);
break;
case 'dataUpdated':
this.onDataUpdated(event);
break;
}
};
// process rowData event
ViewportDatasource.prototype.onRowData = function (event) {
var rowDataFromServer = event.rowDataMap;
this.params.setRowData(rowDataFromServer);
};
// process dataUpdated event
ViewportDatasource.prototype.onDataUpdated = function (event) {
var that = this;
event.changes.forEach(function (change) {
var rowNode = that.params.getRow(change.rowIndex);
// if the rowNode is missing, it means the grid is not displaying that row.
// if the data is missing, it means the rowNode is there, but that data has not
// loaded into it yet, so to early to set delta changes.
if (!rowNode || !rowNode.data) {
return;
}
// rowNode.data[change.columnId] = change.newValue;
// this is a trick, it gets the row to refresh
rowNode.setDataValue(change.columnId, change.newValue);
});
};
// process rowCount event
ViewportDatasource.prototype.onRowCountChanged = function (event) {
var rowCountFromServer = event.rowCount;
// this will get the grid to make set the height of the row container, so we can scroll vertically properly
this.params.setRowCount(rowCountFromServer);
};
function setRowData($http) {
// set up a mock server - real code will not do this, it will contact your
// real server to get what it needs
var mockServer = new MockServer();
$http.get('data.json').then(function(response){
mockServer.init(response.data);
});
var viewportDatasource = new ViewportDatasource(mockServer);
table.api.setViewportDatasource(viewportDatasource);
// put the 'size cols to fit' into a timeout, so that the scroll is taken into consideration
setTimeout(function () {
table.api.sizeColumnsToFit();
}, 100);
}
// setup the grid after the page has finished loading
/* document.addEventListener('DOMContentLoaded', function () {
var gridDiv = document.querySelector('#liveStreamExample');
new agGrid.Grid(gridDiv, table);
// do http request to get our sample data - not using any framework to keep the example self contained.
// you will probably use a framework like JQuery, Angular or something else to do your HTTP calls.
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', 'data.json');
httpRequest.send();
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
var httpResponse = JSON.parse(httpRequest.responseText);
setRowData(httpResponse);
}
};
});*/
};
WatcherTable.prototype.getContextMenuItems = function ($rootScope,params){
var result= [{name:"Show Book", action:WatcherTable.prototype.changeBookSubscription.bind(this,$rootScope,params.node.data)}];
return result;
}
WatcherTable.prototype.onCellDoubleClicked = function ($rootScope,params){
$rootScope.$broadcast("changeBookSubscription",{instrkey:params.data.cus+"."+params.data.isin,boardLabel:params.data.isd+" "+params.data.lbl});
if(params.colDef.field.indexOf("bBid")>-1){
$rootScope.$broadcast("showHitDialog",params);
log("Show hit dialog");
console.log(params);
}
else if(params.colDef.field.indexOf("bAsk")>-1){
$rootScope.$broadcast("showLiftDialog",params);
log("Show lift dialog");
console.log(params);
}
}
WatcherTable.prototype.changeBookSubscription = function ($rootScope,data) {
$rootScope.$broadcast("changeBookSubscription",{instrkey:data.cus+"."+data.isin,boardLabel:data.isd+" "+data.lbl});
}
WatcherTable.prototype.getMainMenuItems = function($rootScope, params){
var prcCols=["bBidPrc","bAskPrc","oBidPrc","oAskPrc"];
var spdCols=["bBidSpd","bAskSpd","oBidSpd","oAskSpd"];
var menuItems= [
{name:'Show Price',
action:function(){
params.columnApi.setColumnsVisible(prcCols, !params.api.gridCore.gridOptions.showPrice);
params.api.gridCore.gridOptions.showPrice= !params.api.gridCore.gridOptions.showPrice;
},
checked: params.api.gridCore.gridOptions.showPrice
},
{name:'Show Spread',
action:function(){
params.columnApi.setColumnsVisible(spdCols, !params.api.gridCore.gridOptions.showSpread);
params.api.gridCore.gridOptions.showSpread= !params.api.gridCore.gridOptions.showSpread;
},
checked: params.api.gridCore.gridOptions.showSpread
},
{
name:'Orders',
subMenu:[
{name:'Live Orders Only',
action:function(){
if (params.api.gridCore.gridOptions.orderFilter==='live'){
params.api.gridCore.gridOptions.orderFilter='';
//TODO filter
}
else {params.api.gridCore.gridOptions.orderFilter='live';
//TODO filter
}
}, checked:(params.api.gridCore.gridOptions.orderFilter==='live')},
{name:'My Orders Only', action:function(){
if (params.api.gridCore.gridOptions.orderFilter==='mine'){
params.api.gridCore.gridOptions.orderFilter='';
//TODO filter
}
else {params.api.gridCore.gridOptions.orderFilter='mine';
//TODO filter
}
}, checked:(params.api.gridCore.gridOptions.orderFilter==='mine')},
{name:'My Firm\'s Orders Only', action:function(){
if (params.api.gridCore.gridOptions.orderFilter==='firm'){
params.api.gridCore.gridOptions.orderFilter='';
//TODO filter
}
else {params.api.gridCore.gridOptions.orderFilter='firm';
//TODO filter
}
}, checked:(params.api.gridCore.gridOptions.orderFilter==='firm')},
]
},
{name: 'Size ...', action: function() {
console.log(params.api.gridCore.gridOptions.orderSize);
$rootScope.$broadcast("orderSizeDialog",{size:parseInt(params.api.gridCore.gridOptions.orderSize)});
},
}
];
return menuItems;
}
你能帮帮我吗?
编辑
我注意到在创建 ViewportDatasource 时没有调用 eventListener 函数 object。怎么强制呢?
编辑 2
我将 ViewportDatasource 声明移出 WatcherTable 范围。现在我已经解决了开始的问题,但是我无法将数据加载到网格中。
我创建了一个 plunker:https://plnkr.co/edit/EEEJULRE72nbPF6G0PCK
(从你今天的问题中摘取的,我认为这里有类似的问题)
您的 plunker 中存在计时问题 - 您的 MockServer 正在尝试在数据可用之前对其进行处理。
您需要做两件事来解决此问题 - 首先是仅在数据在 MockServer 中可用时才尝试设置数据源:
WatcherTable.prototype.setRowData = function ($http) {
// set up a mock server - real code will not do this, it will contact your
// real server to get what it needs
var mockServer = new MockServer();
var that = this;
$http.get('data.json').then(function (response) {
mockServer.init(response.data);
var viewportDatasource = new ViewportDatasource(mockServer);
that.table.api.setViewportDatasource(viewportDatasource);
// put the 'size cols to fit' into a timeout, so that the scroll is taken into consideration
setTimeout(function () {
that.table.api.sizeColumnsToFit();
}, 100);
});
}
其次,沿着相同的主题,您需要防止定期更新在数据准备就绪之前尝试处理数据。在这里,您可以在数据可用后开始定期更新,或者更简单地在尝试使用它之前添加一个检查:
MockServer.prototype.periodicallyUpdateData = function() {
if(!this.allData) return;
我在这里 fork 你的 plunker(进行了上述更改):https://plnkr.co/edit/cY30aHIPydVOjcihX8Zh?p=preview
我正在复制 ag-grid 视口示例,将其放入表示 table 而不是匿名函数的 object 中。我不明白为什么它在尝试连接到模拟服务器时给我标题中的错误,因为它是完全相同的代码。
这是似乎不起作用的代码:
function ViewportDatasource(mockServer) {
this.mockServer = mockServer;
this.connectionId = this.mockServer.connect(this.eventListener.bind(this));
}
ViewportDatasource.prototype.eventListener = function (event) {
switch (event.eventType) {
case 'rowCountChanged':
this.onRowCountChanged(event);
break;
case 'rowData':
this.onRowData(event);
break;
case 'dataUpdated':
this.onDataUpdated(event);
break;
}
};
这是全部object:
function WatcherTable($rootScope,$scope, $http) {
this.FIELD_KEY_ID = "id";
this.FIELD_KEY_ISSUER_SHORT_DESC= "isd";
this.FIELD_KEY_ISSUER = "iss";
this.FIELD_KEY_CUSIP = "cus";
this.FIELD_KEY_ISIN = "isin";
this.FIELD_KEY_BOARD_LABEL = "lbl";
this.FIELD_KEY_IND_SECT_LABEL = "isl";
this.FIELD_KEY_CURR="cur"
this.FIELD_KEY_BEST_BID_SIZE = "bBidSz";
this.FIELD_KEY_BEST_BID_PRICE = "bBidPrc";
this.FIELD_KEY_BEST_ASK_PRICE = "bAskPrc";
this.FIELD_KEY_BEST_ASK_SIZE = "bAskSz";
this.FIELD_KEY_BEST_BID_SPREAD = "bBidSpd";
this.FIELD_KEY_BEST_ASK_SPREAD = "bAskSpd";
this.FIELD_KEY_ORDER_BID_SIZE = "oBidSz";
this.FIELD_KEY_ORDER_BID_PRICE = "oBidPrc";
this.FIELD_KEY_ORDER_ASK_PRICE = "oAskPrc";
this.FIELD_KEY_ORDER_ASK_SIZE = "oAskSz";
this.FIELD_KEY_ORDER_BID_SPREAD = "oBidSpd";
this.FIELD_KEY_ORDER_ASK_SPREAD = "oAskSpd";
this.headerMyOrder="ORDER";
this.headerMyBidOrder="BID ORDER";
this.headerMyAskOrder="ASK ORDER";
this.cols = [{
headerName : "Security Info",
marryChildren : true,
children : [{
headerName : "Issuer Short Desc.",
field : this.FIELD_KEY_ISSUER_SHORT_DESC,
//width : 0,
//hide : true
},
{
headerName : "Industry Sector Label",
field : this.FIELD_KEY_IND_SECT_LABEL,
//width : 80,
filter: 'set',
filterParams: { values: ['Advertising', 'Aerospace/Defense', 'Agriculture', 'Airlines', 'Apparel', 'Auto Manufacturers', 'Auto Parts&Equipment', 'Banks', 'Basic Materials', 'Beverages', 'Biotechnology', 'Building Materials', 'Chemicals', 'Coal', 'Commercial Services', 'Communications', 'Computers', 'Consumer, Cyclical', 'Consumer, Non-cyclical', 'Cosmetics/Personal Care', 'Distribution/Wholesale', 'Diversified', 'Electrical Compo&Equip', 'Electronics', 'Energy', 'Energy-Alternate Sources', 'Engineering&Construction', 'Entertainment', 'Machinery-Constr&Mining', 'Household Products/WaresIndustrial', 'Insurance', 'Internet', 'Investment Companies', 'Iron/Steel', 'Kangaroos', 'Leisure Time', 'Lodging', 'Machinery-Constr&Mining', 'Machinery-Diversified', 'Media', 'Metal Fabricate/Hardware', 'Mining', 'Miscellaneous Manufactur', 'Multi-National', 'Office Furnishings', 'Office/Business ', 'Oil&Gas', 'Oil&Gas Services', 'Packaging&Containers', 'Pharmaceuticals', 'Pipelines', 'Real Estate', 'Regional(state/provnc)', 'REITS', 'Retail', 'Savings&Loans'],
newRowsAction: 'keep'},
},
{
headerName : "Board Label",
field : this.FIELD_KEY_BOARD_LABEL,
//width : 80,
filter: 'text',
filterParams: { apply: true }
}, {
headerName : "CUSIP",
field : this.FIELD_KEY_CUSIP,
//width : 150,
//suppressFilter: true
},
{
headerName : "ISIN",
field : this.FIELD_KEY_ISIN,
//width : 150,
//suppressFilter: true
},
{
headerName : "Currency",
field : this.FIELD_KEY_CURR,
//width : 150,
//suppressFilter: true
}
]},
{
headerName : "Best",
marryChildren : true,
children : [ {
headerName : "Bid Size",
pinned: 'right',
field : this.FIELD_KEY_BEST_BID_SIZE,
cellStyle: {'border-left': '1px solid #E82043', 'color':'#E82043', 'font-weight':'bold', 'text-align':'right'},
cellRenderer: BidRenderer,
filter:'number',
//width : 125,
//suppressFilter: true
}, {
headerName : "Bid Price",
pinned: 'right',
field : this.FIELD_KEY_BEST_BID_PRICE,
cellStyle: {'border-right': '1px solid #E82043', 'color':'#E82043', 'font-weight':'bold', 'text-align':'right'},
//cellRenderer: 'animateShowChange',
cellFormatter: numberFormatter,
cellRenderer: BidRenderer,
width : 125,
filter:'number',
//suppressFilter: true
},
{
headerName : "Ask Price",
pinned: 'right',
field : this.FIELD_KEY_BEST_ASK_PRICE,
//cellRenderer: 'animateShowChange',
cellFormatter: numberFormatter,
cellRenderer: AskRenderer,
cellStyle: {'color':'#19B092', 'font-weight':'bold', 'text-align':'right'},
filter:'number',
//width : 125,
//suppressFilter: true
},
{
headerName : "Ask Size",
pinned: 'right',
field : this.FIELD_KEY_BEST_ASK_SIZE,
cellStyle: {'border-right': '1px solid #19B092', 'color':'#19B092', 'font-weight':'bold', 'text-align':'right'},
cellRenderer: AskRenderer,
filter:'number',
//width : 125,
//suppressFilter: true
} ]
} ];
//definizione della tabella//// rowModelType: 'virtual', rowModelType: 'pagination',
this.table = {
showPrice: true,
showSpread: true,
orderSize: 0,
orderFilter: '',
enableServerSideFilter: true,
enableServerSideSorting: true,
sortingOrder: ['desc','asc',null],
enableColResize : true,
debug : true,
rowSelection : 'multiple',
rowDeselection : true,
columnDefs : this.cols,
rowModelType : 'viewport',
headerHeight: 20,
rowHeight: 20,
viewportRowModelPageSize:30,
viewportRowModelBufferSize: 15,
suppressColumnVirtualisation: true,
suppressMenuColumnPanel: true,
onCellDoubleClicked: WatcherTable.prototype.onCellDoubleClicked.bind(this,$rootScope),
getContextMenuItems: WatcherTable.prototype.getContextMenuItems.bind(this,$rootScope),
getMainMenuItems: WatcherTable.prototype.getMainMenuItems.bind(this, $rootScope),
getRowNodeId: function (data) {
// the code is unique, so perfect for the id
return data.isin;
},
onGridReady:setRowData($http)
};
function numberFormatter(params) {
if (typeof params.value === 'number') {
return params.value.toFixed(4);
} else {
return params.value;
}
}
function BidRenderer () {}
BidRenderer.prototype.init = function(params) {
// create the cell
this.eGui = document.createElement('div');
this.eGui.innerHTML = '<div></div>';
// set value into cell
this.eValue = this.eGui.querySelectorAll('div')[0];
this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;
};
// gets called once when grid ready to insert the element
BidRenderer.prototype.getGui = function() {
return this.eGui;
};
// gets called whenever the user gets the cell to refresh
BidRenderer.prototype.refresh = function(params) {
// set value into cell again
this.eGui.innerHTML = '<div class="bid"></div>';
this.eValue = this.eGui.querySelectorAll('div')[0];
this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;
};
function AskRenderer () {}
AskRenderer.prototype.init = function(params) {
// create the cell
this.eGui = document.createElement('div');
this.eGui.innerHTML = '<div></div>';
// set value into cell
this.eValue = this.eGui.querySelectorAll('div')[0];
this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;
};
// gets called once when grid ready to insert the element
AskRenderer.prototype.getGui = function() {
return this.eGui;
};
// gets called whenever the user gets the cell to refresh
AskRenderer.prototype.refresh = function(params) {
// set value into cell again
this.eGui.innerHTML = '<div class="ask"></div>';
this.eValue = this.eGui.querySelectorAll('div')[0];
this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;
};
// client code (ie your code) will call this constructor, pass in whatever you need for the
// viewport to do it's job
function ViewportDatasource(mockServer) {
this.mockServer = mockServer;
this.connectionId = this.mockServer.connect(this.eventListener.bind(this));
}
// gets called by the grid, tells us what rows the grid is displaying, so time for
// us to tell the server to give us the rows for that displayed range
ViewportDatasource.prototype.setViewportRange = function (firstRow, lastRow) {
this.mockServer.setViewportRange(this.connectionId, firstRow, lastRow);
};
// gets called by the grid, provides us with the callbacks we need
ViewportDatasource.prototype.init = function (params) {
this.params = params;
};
// gets called by grid, when grid is destroyed or this datasource is swapped out for another one
ViewportDatasource.prototype.destroy = function () {
this.mockServer.disconnect(this.connectionId);
};
// manages events back from the server
ViewportDatasource.prototype.eventListener = function (event) {
switch (event.eventType) {
case 'rowCountChanged':
this.onRowCountChanged(event);
break;
case 'rowData':
this.onRowData(event);
break;
case 'dataUpdated':
this.onDataUpdated(event);
break;
}
};
// process rowData event
ViewportDatasource.prototype.onRowData = function (event) {
var rowDataFromServer = event.rowDataMap;
this.params.setRowData(rowDataFromServer);
};
// process dataUpdated event
ViewportDatasource.prototype.onDataUpdated = function (event) {
var that = this;
event.changes.forEach(function (change) {
var rowNode = that.params.getRow(change.rowIndex);
// if the rowNode is missing, it means the grid is not displaying that row.
// if the data is missing, it means the rowNode is there, but that data has not
// loaded into it yet, so to early to set delta changes.
if (!rowNode || !rowNode.data) {
return;
}
// rowNode.data[change.columnId] = change.newValue;
// this is a trick, it gets the row to refresh
rowNode.setDataValue(change.columnId, change.newValue);
});
};
// process rowCount event
ViewportDatasource.prototype.onRowCountChanged = function (event) {
var rowCountFromServer = event.rowCount;
// this will get the grid to make set the height of the row container, so we can scroll vertically properly
this.params.setRowCount(rowCountFromServer);
};
function setRowData($http) {
// set up a mock server - real code will not do this, it will contact your
// real server to get what it needs
var mockServer = new MockServer();
$http.get('data.json').then(function(response){
mockServer.init(response.data);
});
var viewportDatasource = new ViewportDatasource(mockServer);
table.api.setViewportDatasource(viewportDatasource);
// put the 'size cols to fit' into a timeout, so that the scroll is taken into consideration
setTimeout(function () {
table.api.sizeColumnsToFit();
}, 100);
}
// setup the grid after the page has finished loading
/* document.addEventListener('DOMContentLoaded', function () {
var gridDiv = document.querySelector('#liveStreamExample');
new agGrid.Grid(gridDiv, table);
// do http request to get our sample data - not using any framework to keep the example self contained.
// you will probably use a framework like JQuery, Angular or something else to do your HTTP calls.
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', 'data.json');
httpRequest.send();
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
var httpResponse = JSON.parse(httpRequest.responseText);
setRowData(httpResponse);
}
};
});*/
};
WatcherTable.prototype.getContextMenuItems = function ($rootScope,params){
var result= [{name:"Show Book", action:WatcherTable.prototype.changeBookSubscription.bind(this,$rootScope,params.node.data)}];
return result;
}
WatcherTable.prototype.onCellDoubleClicked = function ($rootScope,params){
$rootScope.$broadcast("changeBookSubscription",{instrkey:params.data.cus+"."+params.data.isin,boardLabel:params.data.isd+" "+params.data.lbl});
if(params.colDef.field.indexOf("bBid")>-1){
$rootScope.$broadcast("showHitDialog",params);
log("Show hit dialog");
console.log(params);
}
else if(params.colDef.field.indexOf("bAsk")>-1){
$rootScope.$broadcast("showLiftDialog",params);
log("Show lift dialog");
console.log(params);
}
}
WatcherTable.prototype.changeBookSubscription = function ($rootScope,data) {
$rootScope.$broadcast("changeBookSubscription",{instrkey:data.cus+"."+data.isin,boardLabel:data.isd+" "+data.lbl});
}
WatcherTable.prototype.getMainMenuItems = function($rootScope, params){
var prcCols=["bBidPrc","bAskPrc","oBidPrc","oAskPrc"];
var spdCols=["bBidSpd","bAskSpd","oBidSpd","oAskSpd"];
var menuItems= [
{name:'Show Price',
action:function(){
params.columnApi.setColumnsVisible(prcCols, !params.api.gridCore.gridOptions.showPrice);
params.api.gridCore.gridOptions.showPrice= !params.api.gridCore.gridOptions.showPrice;
},
checked: params.api.gridCore.gridOptions.showPrice
},
{name:'Show Spread',
action:function(){
params.columnApi.setColumnsVisible(spdCols, !params.api.gridCore.gridOptions.showSpread);
params.api.gridCore.gridOptions.showSpread= !params.api.gridCore.gridOptions.showSpread;
},
checked: params.api.gridCore.gridOptions.showSpread
},
{
name:'Orders',
subMenu:[
{name:'Live Orders Only',
action:function(){
if (params.api.gridCore.gridOptions.orderFilter==='live'){
params.api.gridCore.gridOptions.orderFilter='';
//TODO filter
}
else {params.api.gridCore.gridOptions.orderFilter='live';
//TODO filter
}
}, checked:(params.api.gridCore.gridOptions.orderFilter==='live')},
{name:'My Orders Only', action:function(){
if (params.api.gridCore.gridOptions.orderFilter==='mine'){
params.api.gridCore.gridOptions.orderFilter='';
//TODO filter
}
else {params.api.gridCore.gridOptions.orderFilter='mine';
//TODO filter
}
}, checked:(params.api.gridCore.gridOptions.orderFilter==='mine')},
{name:'My Firm\'s Orders Only', action:function(){
if (params.api.gridCore.gridOptions.orderFilter==='firm'){
params.api.gridCore.gridOptions.orderFilter='';
//TODO filter
}
else {params.api.gridCore.gridOptions.orderFilter='firm';
//TODO filter
}
}, checked:(params.api.gridCore.gridOptions.orderFilter==='firm')},
]
},
{name: 'Size ...', action: function() {
console.log(params.api.gridCore.gridOptions.orderSize);
$rootScope.$broadcast("orderSizeDialog",{size:parseInt(params.api.gridCore.gridOptions.orderSize)});
},
}
];
return menuItems;
}
你能帮帮我吗?
编辑
我注意到在创建 ViewportDatasource 时没有调用 eventListener 函数 object。怎么强制呢?
编辑 2
我将 ViewportDatasource 声明移出 WatcherTable 范围。现在我已经解决了开始的问题,但是我无法将数据加载到网格中。
我创建了一个 plunker:https://plnkr.co/edit/EEEJULRE72nbPF6G0PCK
(从你今天的问题中摘取的,我认为这里有类似的问题)
您的 plunker 中存在计时问题 - 您的 MockServer 正在尝试在数据可用之前对其进行处理。
您需要做两件事来解决此问题 - 首先是仅在数据在 MockServer 中可用时才尝试设置数据源:
WatcherTable.prototype.setRowData = function ($http) {
// set up a mock server - real code will not do this, it will contact your
// real server to get what it needs
var mockServer = new MockServer();
var that = this;
$http.get('data.json').then(function (response) {
mockServer.init(response.data);
var viewportDatasource = new ViewportDatasource(mockServer);
that.table.api.setViewportDatasource(viewportDatasource);
// put the 'size cols to fit' into a timeout, so that the scroll is taken into consideration
setTimeout(function () {
that.table.api.sizeColumnsToFit();
}, 100);
});
}
其次,沿着相同的主题,您需要防止定期更新在数据准备就绪之前尝试处理数据。在这里,您可以在数据可用后开始定期更新,或者更简单地在尝试使用它之前添加一个检查:
MockServer.prototype.periodicallyUpdateData = function() {
if(!this.allData) return;
我在这里 fork 你的 plunker(进行了上述更改):https://plnkr.co/edit/cY30aHIPydVOjcihX8Zh?p=preview