AngularJs中动态html包含指令问题
在使用ui-grid来渲染数据列表的时候,遇到一个问题就是当数据量太大的时候,对于渲染好了的列表,如果再次修改这个列表,重新绑定数据集,ui-grid处理非常慢(大致看了一下源码,里面对于重新绑定的数据集,不会去创建表格,只会从当前的表格中克隆节点,然后再处理,并且其中需要销毁很多的监听器)。一直解决不了,换了一种方式,当数据变化的时候,我就销毁当前表格(其实就是移除了dom节点),然后重新创建一个动态的html片段代码,里面绑定有ui-grid的指令。当我将动态的html插入到文档中之后,然后再设置表格数据,发现表格并没有渲染。
//创建新表格
$scope.createNewGrid = function(elementId,headers,datas){
//获取旧容器
var container = document.getElementById(elementId);
var childList = container.childNodes;
var oldGridContainer = null;
//找到Grid容器
for(var i = 0; i < childList.length; i ++){
if(/DIV/i.test(childList[i].nodeName)){
oldGridContainer = childList[i];
break;
}
}
//新表格容器
var newGridContainer = oldGridContainer.cloneNode(false);
//销毁就容器
container.innerHTML = "";
$scope.newGridOptions = createGridOptions();
newGridContainer.setAttribute("ui-grid","newGridOptions");
container.appendChild(newGridContainer);
//设置数据集
$scope.newGridOptions.data = datas;
console.log(newGridContainer);
/*console.log(uiGrid);*/
}
上面代码的问题就是,我获取的以前的节点并克隆了一份,当我插入文档之后,该节点包含指令没有被编译,指令没有和作用域连接起来,因此导致了问题。
解决方案:使用angular的$compile来编译指令,compile可以将一个HTML字符串或者DOM编译成模板,该模板能够与scope链接起来,也就是说直接插入一段html片段到页面中,虽然能插入进去,但是angular并没有编译,所以任何ng事件指令绑定都是无效的,通过compile能够将html片段先编译后再插入 。
html代码片段:后面构造表格函数传入的elementId就是这个Id,ui-grid内容就渲染在这个dom之中
<div class="row">
<div class="col-md-12" style="padding: 0px;" id="rightGrid">
</div>
</div>
关键代码:
//编译指令,并挂载作用域
container.html($compile("<div ui-grid='" + gridOptionsIdentifier +"' ui-grid-selection ui-grid-exporter ui-grid-resize-columns ui-grid-auto-resize></div>")($scope));
改进后的表格创建函数:
//创建新表格API
$scope.createNewGrid = function(elementId,headers,datas){
//获取旧容器
var container = $("#"+elementId);
//销毁以前的Grid容器
container.html("");
//生成Grid唯一标识
var gridOptionsIdentifier = "gridOptions_"+(new Date()).getTime();
//生成配置项
$scope[gridOptionsIdentifier] = createGridOptions();
//编译指令,并挂载作用域
container.html($compile("<div ui-grid='" + gridOptionsIdentifier +"' ui-grid-selection ui-grid-exporter ui-grid-resize-columns ui-grid-auto-resize></div>")($scope));
//挂载数据
$scope[gridOptionsIdentifier].columnDefs = headers;
$scope[gridOptionsIdentifier].data = datas;
//将表格绑定到全局变量,以便于后面获取表格API
if(elementId == "leftGrid"){
$scope.leftGridOptions = $scope[gridOptionsIdentifier];
}
else if(elementId == "rightGrid"){
$scope.rightGridOptions = $scope[gridOptionsIdentifier];
}
else {
$scope.resultGridOptions = $scope[gridOptionsIdentifier];
}
console.clear();
}
创建表格配置代码:
//创建表格配置
function createGridOptions(){
var gridOptions = {};
(function(arg){
arg = gridOptions || {};
arg.enableSorting = true;
arg.useExternalSorting= false;//是否使用自定义排序规则
arg.enableGridMenu= true; //是否显示grid菜单
arg.enableHorizontalScrollbar= 1; //grid水平滚动条是否显示, 0-不显示 1-显示
arg.enableVerticalScrollbar= 1; //grid垂直滚动条是否显示, 0-不显示 1-显示
//----------- 选中 ----------------------
arg.showGridFooter= true, //是否显示grid footer
arg.enableFooterTotalSelected= true; // 是否显示选中的总数,默认为true, 如果显示,showGridFooter 必须为true
arg.enableFullRowSelection= false; //是否点击行任意位置后选中,默认为false,当为true时,checkbox可以显示但是不可选中
arg.enableRowHeaderSelection= true; //是否显示选中checkbox框 ,默认为true
arg.enableRowSelection= true; // 行选择是否可用,默认为true;
arg.enableSelectAll= true; // 选择所有checkbox是否可用,默认为true;
arg.enableSelectionBatchEvent= true; //默认true
arg.isRowSelectable= function (row) { //GridRow
$scope.index += 1;
if ($scope.index == 1) {
row.grid.api.selection.selectRow(row.entity); // 选中行
}
},
arg.modifierKeysToMultiSelect= false;//默认false,为true时只能 按ctrl或shift键进行多选, multiSelect 必须为true;
arg.multiSelect= true;// 是否可以选择多个,默认为true;
arg.noUnselect= false;//默认false,选中后是否可以取消选中
arg.selectionRowHeaderWidth= 30;//默认30 ,设置选择列的宽度;
//---------------api---------------------
arg.onRegisterApi=function (gridApi) {
arg.gridApi = gridApi;
//行选中事件
arg.gridApi.selection.on.rowSelectionChanged(arg, function (row, event) {
if (row) {
arg.testRow = row.entity;
arg.isSelected = row.isSelected;
//console.log($scope.gridApi.selection.getSelectedRows());
}
});
};
//获取表格所有数据
arg.getAllRows = function(){
return arg.data;
}
//----------------导出--------------------
arg.exporterCsvColumnSeparator = ',';
arg.exporterOlderExcelCompatibility = true;//是否兼容低版本excel
arg.exporterHeaderFilterUseName = true;
arg.exporterMenuCsv = true;
arg.exporterMenuLabel = "导出";
arg.exporterMenuPdf = false;
return arg;
})(gridOptions);
return gridOptions;
}