如何在gridx的cell中显示控件
1个回答
推荐于2016-09-25
展开全部
在gridx的列定义中,一个decorator方法可以被用来在cell中显示任何HTML/CSS. 但是有时候这稍显不够。当cell中需要放入复杂的控件时,从decorator方法中返回的纯string不再有效。所以gridx/modules/CellWidget模块在这是显示了作用。
为何是CellWidget
CellWidget模块通过grid的body模块中的onAfterRow事件将widget附加到cell节点中。其中的关键是如何才能高效地完成这个工作。
Grid的body随着时间不断刷新,刷新的原因可以是排序,过滤,分页,虚拟滚动,改变值,展开树节点,等等。每次body被刷新,行被重新,并且onAfterRow事件将会被处罚。如果我们总是在onAfterRow事件中创建新的widget,那将会非常浪费。如果你点击header两次为了要是的一列降序排序,许多widget将会被立刻摧毁。所以一些缓存机制必须被建立。第一个方法是为在每个cell中使用一个widget,无论被刷新多少次。这解决了一些刷新问题,但是如果我们有100000行,这仍然不高效。试想如果一个用户慢慢地滚动这个巨大的grid来看每一行,最终将会有多少widget被创建!
所以CellWidget的目的是创建尽可能少的控件。方法是使用set('value',...)方法在row之间重用控件。
如何使用CellWidget
在控件上设置值通常比创建一个新控件快。这是一个好方法,但是需要用户意识到重用这件事情。让我们首先看一下如何使用CellWidget模块:
var grid = new Grid({
cacheClass: 'gridx/core/model/cache/Async',
store: someStore,
structure: [
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
decorator: function(){
return "<div data-dojo-type='dijit.ProgressBar' data-dojo-props='maximum: 1' " +
"class='gridxHasGridCellValue' style='width: 100%;'></div>";
}
}
],
modules: [
"gridx/modules/CellWidget"
]
});
首先,不要忘记载入所有必要的资源: store, cache, 模块和你想要在cell中展示的widget。如果你仍然在创建一个gridx的时候遇到麻烦,请阅读 这篇教程 .
第二,在你想要显示widgets的列中将 widgetsInCell 属性设置为true。CellWidget模块将只会在这些列上有效。
第三,在你的设置 widgetsInCell 的列中提供 decorator 方法。
从decorator方法中返回模板字符串
这里你将看到第一个小技巧: decorator 并没有任何的参数。这并不是当 widgetsInCell 为false的情况。通常当前的cell数据会被传入,和row Id和Index一起。如果某些特定的cell数据被传入,我们将如何重用他们?所以这个template string不能包含任何特定的行信息。在上面的示例中,一个dijit/ProgressBar被放进template中,他的参数可以在data-dojo-props中被加入。注意这个 gridxhasGridCellValue class ,这是关于widgets被重用的第二个技巧。CellWidget模块将会在渲染每一行时自动查找所有含有这个class的widget,并且调用set('value')在widget中设置合适的值。
在setCellValue中设置widgets
在上面的例子中,在调用 widget 的 set('value') 之前不需要转换数据,因此事情显得比较简单。在设置widget值的时候,如果你想做一些有趣的事情,该怎么办? setCellValue 方法在这个时候派上了用处。
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
decorator: function(){
return "<div data-dojo-type='dijit.ProgressBar' data-dojo-props='maximum: 1' " +
"data-dojo-attach-point='progBar' style='width: 100%;'></div>";
},
setCellValue: function(gridData, storeData, cellWidget){
var data = doSomethingIntersting(gridData);
cellWidget.progBar.set('value', data);
// cellWidget.cell give you full access to everything you want.
var rowIndex = cellWidget.cell.row.index();
}
}
setCellValue 方法会在每一行被render的时候被调用。当这个方法被调用时,widget已经被创建并且你能完全控制widget。你可以在widgets上设置值,改变css,或者操纵dom节点并且添加事件。这个方法中的第三个参数'cellWidget'引用了cell widget本身,这是拥有从'decorater'方法中返回的template string的widget,所以你可以访问任何的在控件中定义的“dojo attach point”。第一和第二个参数是当前cell的grid data与store data。他们只有当'formatter'方法被提供时才会有差别。你可以通过cellWidget.cell来获取当前的cell,从中你可以获取任何你需要的东西。
如何处理widget事件
但是请记住widgets("cell widget"作为一个整体)是在不同的行之间被重用。所以如果你在setCellValue方法中绑定了一些事件或者改变了一些dom节点的时候,这些改变将会在被其他行重用时被保留。如果你一直连接事件而不断开事件,将会有巨大的内存泄漏风险。所以合适的方法是在setCellValue中连接并且断开事件。例如
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
decorator: function(){
return "<button data-dojo-type='dijit.form.Button' data-dojo-attach-point='btn'></button>";
},
setCellValue: function(gridData, storeData, cellWidget){
cellWidget.btn.set('label', gridData);
if(cellWidget.btn._cnnt){
// Remove previously connected events to avoid memory leak.
cellWidget.btn._cnnt.remove();
}
cellWidget.btn._cnnt = dojo.connect(cellWidget.btn, 'onClick', function(e){
alert(gridData);
// do your job here......
});
}
}
我承认,这看起来不怎么直观。所以在gridx 1.2中一个新的方法(回调)在会被引入以使得这个工作更加简便:
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
decorator: function(){
return "<button data-dojo-type='dijit.form.Button' data-dojo-attach-point='btn'></button>";
},
setCellValue: function(gridData, storeData, cellWidget){
cellWidget.btn.set('label', gridData);
},
getCellWidgetConnects: function(cellWidget, cell){
// return an array of connection arguments
return [
[cellWidget.btn, 'onClick', function(e){
alert(cell.data());
// do your job here.....
}]
];
}
}
有了这个getCellWidgetConnects,gridx可以为你管理事件链接(句柄)。连接和断开都会被自动执行。
其他高级的回调函数
初次之外,gridx 1.2添加了另外2个方法来为你的工作提供更加有意义的命名:
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
decorator: function(){
return "<button data-dojo-type='dijit.form.Button' data-dojo-attach-point='btn'></button>";
},
setCellValue: function(gridData, storeData, cellWidget){
cellWidget.btn.set('label', gridData);
},
getCellWidgetConnects: function(cellWidget, cell){
// return an array of connection arguments
return [
[cellWidget.btn, 'onClick', function(e){
alert(cell.data());
// do your job here.....
}]
];
},
initializeCellWidget: function(cellWidget, cell){
// create extra widgets or manipulate dom nodes that depends on current cell context.
cellWidget.anotherButton = new Button({...});
cellWidget.domNode.append(cellWidget.anotherButton.domNode);
},
uninitializeCellWidget: function(cellWidget, cell){
// don't forget to undo the changes you made in initializeCellWidget, so that it can be reused among different rows.
cellWidget.anotherButton.destroy();
}
}
如你所见,事实上你可以在setCellValue方法中做这些事情。这个新方法只是提供了更多的语义,使你的代码更加易于阅读并且省去了你添加额外的注释的功夫。
创建控件的编程方式
如果你 曾经用过DataGrid , 你可能会对于在 f ormatter 方法中返回widget的方式感到熟悉,并且对于写 t emplate string的方式感到 变扭。因此你可以使用 onCellWidgetCreated 事件,甚至 省略“ decorator ” 方法(gridx 1.2之后) :
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
onCellWidgetCreated: function(cellWidget, column){
var btn = new Button({...});
btn.placeAt(cellWidget.domNode);
}
}
onCellWidgetCreated 只当一个新的cell widget被创建 时 被调用。它不会在widget 重用时 被调用。跟decorator 方法 相同,不应该在此处使用特定行的信息。
以下是如何在gridx的cell 中显示widget的结论:
为grid 引入 gridx/moduels/CellWidge t模块
在列设置中将 widgetsIn Cell 设置为true
在 decorator 方法 中返回模板string ,或者在 onCellWidgetCreated 事件处理 函数中创建 控件,或者两者皆执行
在 setCell Value 方法中设置widget的值(可选)
在 getCellWidgetConnects 中提供 事件 连接(可选, gridx 1.2 之后 )
在 initialCellWidget 和 Uninit ialCellWidget 中做额外的操作(可选,gridx 1.2之后)
为何是CellWidget
CellWidget模块通过grid的body模块中的onAfterRow事件将widget附加到cell节点中。其中的关键是如何才能高效地完成这个工作。
Grid的body随着时间不断刷新,刷新的原因可以是排序,过滤,分页,虚拟滚动,改变值,展开树节点,等等。每次body被刷新,行被重新,并且onAfterRow事件将会被处罚。如果我们总是在onAfterRow事件中创建新的widget,那将会非常浪费。如果你点击header两次为了要是的一列降序排序,许多widget将会被立刻摧毁。所以一些缓存机制必须被建立。第一个方法是为在每个cell中使用一个widget,无论被刷新多少次。这解决了一些刷新问题,但是如果我们有100000行,这仍然不高效。试想如果一个用户慢慢地滚动这个巨大的grid来看每一行,最终将会有多少widget被创建!
所以CellWidget的目的是创建尽可能少的控件。方法是使用set('value',...)方法在row之间重用控件。
如何使用CellWidget
在控件上设置值通常比创建一个新控件快。这是一个好方法,但是需要用户意识到重用这件事情。让我们首先看一下如何使用CellWidget模块:
var grid = new Grid({
cacheClass: 'gridx/core/model/cache/Async',
store: someStore,
structure: [
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
decorator: function(){
return "<div data-dojo-type='dijit.ProgressBar' data-dojo-props='maximum: 1' " +
"class='gridxHasGridCellValue' style='width: 100%;'></div>";
}
}
],
modules: [
"gridx/modules/CellWidget"
]
});
首先,不要忘记载入所有必要的资源: store, cache, 模块和你想要在cell中展示的widget。如果你仍然在创建一个gridx的时候遇到麻烦,请阅读 这篇教程 .
第二,在你想要显示widgets的列中将 widgetsInCell 属性设置为true。CellWidget模块将只会在这些列上有效。
第三,在你的设置 widgetsInCell 的列中提供 decorator 方法。
从decorator方法中返回模板字符串
这里你将看到第一个小技巧: decorator 并没有任何的参数。这并不是当 widgetsInCell 为false的情况。通常当前的cell数据会被传入,和row Id和Index一起。如果某些特定的cell数据被传入,我们将如何重用他们?所以这个template string不能包含任何特定的行信息。在上面的示例中,一个dijit/ProgressBar被放进template中,他的参数可以在data-dojo-props中被加入。注意这个 gridxhasGridCellValue class ,这是关于widgets被重用的第二个技巧。CellWidget模块将会在渲染每一行时自动查找所有含有这个class的widget,并且调用set('value')在widget中设置合适的值。
在setCellValue中设置widgets
在上面的例子中,在调用 widget 的 set('value') 之前不需要转换数据,因此事情显得比较简单。在设置widget值的时候,如果你想做一些有趣的事情,该怎么办? setCellValue 方法在这个时候派上了用处。
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
decorator: function(){
return "<div data-dojo-type='dijit.ProgressBar' data-dojo-props='maximum: 1' " +
"data-dojo-attach-point='progBar' style='width: 100%;'></div>";
},
setCellValue: function(gridData, storeData, cellWidget){
var data = doSomethingIntersting(gridData);
cellWidget.progBar.set('value', data);
// cellWidget.cell give you full access to everything you want.
var rowIndex = cellWidget.cell.row.index();
}
}
setCellValue 方法会在每一行被render的时候被调用。当这个方法被调用时,widget已经被创建并且你能完全控制widget。你可以在widgets上设置值,改变css,或者操纵dom节点并且添加事件。这个方法中的第三个参数'cellWidget'引用了cell widget本身,这是拥有从'decorater'方法中返回的template string的widget,所以你可以访问任何的在控件中定义的“dojo attach point”。第一和第二个参数是当前cell的grid data与store data。他们只有当'formatter'方法被提供时才会有差别。你可以通过cellWidget.cell来获取当前的cell,从中你可以获取任何你需要的东西。
如何处理widget事件
但是请记住widgets("cell widget"作为一个整体)是在不同的行之间被重用。所以如果你在setCellValue方法中绑定了一些事件或者改变了一些dom节点的时候,这些改变将会在被其他行重用时被保留。如果你一直连接事件而不断开事件,将会有巨大的内存泄漏风险。所以合适的方法是在setCellValue中连接并且断开事件。例如
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
decorator: function(){
return "<button data-dojo-type='dijit.form.Button' data-dojo-attach-point='btn'></button>";
},
setCellValue: function(gridData, storeData, cellWidget){
cellWidget.btn.set('label', gridData);
if(cellWidget.btn._cnnt){
// Remove previously connected events to avoid memory leak.
cellWidget.btn._cnnt.remove();
}
cellWidget.btn._cnnt = dojo.connect(cellWidget.btn, 'onClick', function(e){
alert(gridData);
// do your job here......
});
}
}
我承认,这看起来不怎么直观。所以在gridx 1.2中一个新的方法(回调)在会被引入以使得这个工作更加简便:
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
decorator: function(){
return "<button data-dojo-type='dijit.form.Button' data-dojo-attach-point='btn'></button>";
},
setCellValue: function(gridData, storeData, cellWidget){
cellWidget.btn.set('label', gridData);
},
getCellWidgetConnects: function(cellWidget, cell){
// return an array of connection arguments
return [
[cellWidget.btn, 'onClick', function(e){
alert(cell.data());
// do your job here.....
}]
];
}
}
有了这个getCellWidgetConnects,gridx可以为你管理事件链接(句柄)。连接和断开都会被自动执行。
其他高级的回调函数
初次之外,gridx 1.2添加了另外2个方法来为你的工作提供更加有意义的命名:
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
decorator: function(){
return "<button data-dojo-type='dijit.form.Button' data-dojo-attach-point='btn'></button>";
},
setCellValue: function(gridData, storeData, cellWidget){
cellWidget.btn.set('label', gridData);
},
getCellWidgetConnects: function(cellWidget, cell){
// return an array of connection arguments
return [
[cellWidget.btn, 'onClick', function(e){
alert(cell.data());
// do your job here.....
}]
];
},
initializeCellWidget: function(cellWidget, cell){
// create extra widgets or manipulate dom nodes that depends on current cell context.
cellWidget.anotherButton = new Button({...});
cellWidget.domNode.append(cellWidget.anotherButton.domNode);
},
uninitializeCellWidget: function(cellWidget, cell){
// don't forget to undo the changes you made in initializeCellWidget, so that it can be reused among different rows.
cellWidget.anotherButton.destroy();
}
}
如你所见,事实上你可以在setCellValue方法中做这些事情。这个新方法只是提供了更多的语义,使你的代码更加易于阅读并且省去了你添加额外的注释的功夫。
创建控件的编程方式
如果你 曾经用过DataGrid , 你可能会对于在 f ormatter 方法中返回widget的方式感到熟悉,并且对于写 t emplate string的方式感到 变扭。因此你可以使用 onCellWidgetCreated 事件,甚至 省略“ decorator ” 方法(gridx 1.2之后) :
{ id: 'progress', field: 'progress', name: 'Install Progress',
widgetsInCell: true,
onCellWidgetCreated: function(cellWidget, column){
var btn = new Button({...});
btn.placeAt(cellWidget.domNode);
}
}
onCellWidgetCreated 只当一个新的cell widget被创建 时 被调用。它不会在widget 重用时 被调用。跟decorator 方法 相同,不应该在此处使用特定行的信息。
以下是如何在gridx的cell 中显示widget的结论:
为grid 引入 gridx/moduels/CellWidge t模块
在列设置中将 widgetsIn Cell 设置为true
在 decorator 方法 中返回模板string ,或者在 onCellWidgetCreated 事件处理 函数中创建 控件,或者两者皆执行
在 setCell Value 方法中设置widget的值(可选)
在 getCellWidgetConnects 中提供 事件 连接(可选, gridx 1.2 之后 )
在 initialCellWidget 和 Uninit ialCellWidget 中做额外的操作(可选,gridx 1.2之后)
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询