上篇给大家介绍了,下面重点给大家介绍JS 组件系列之BootstrapTable的treegrid功能,需要的的朋友一起学习吧!
一、效果预览
全部折叠
展开一级
全部展开
二、代码示例
怎么样?效果还行吧。给出js的源码供大家参考。
1) {
func = window;
$.each(names,f) {
func = func[f];
});
} else {
func = window[name];
}
}
if (typeof func === 'object') {
return func;
}
if (typeof func === 'function') {
return func.apply(self,args);
}
if (!func && typeof name === 'string' && sprintf.apply(this,[name].concat(args))) {
return sprintf.apply(this,[name].concat(args));
}
return defaultValue;
};
var getItemField = function (item,field) {
var value = item;
if (typeof field !== 'string' || item.hasOwnProperty(field)) {
return item[field];
}
var props = field.split('.');
for (var p in props) {
value = value[props[p]];
}
return value;
};
var getParent = function (node,source,field) {
var data = [];
var items = $.grep(source,function (item,index) {
return node.ParentId == item[field];
});
$.each(items,function (index,item) {
data.splice(0,item);
var child = getParent(item,field);
$.each(child,n) {
data.splice(0,n);
});
});
return data;
};
var getChild = function (node,index) {
return item.ParentId == node[field];
});
$.each(items,item) {
data.push(item);
var child = getChild(item,n) {
data.push(n);
});
});
return data;
};
//调用bootstrapTable组件的构造器得到对象
var BootstrapTable = $.fn.bootstrapTable.Constructor,_initData = BootstrapTable.prototype.initData,_initPagination = BootstrapTable.prototype.initPagination,_initBody = BootstrapTable.prototype.initBody;
//重写bootstrapTable的initData方法
BootstrapTable.prototype.initData = function () {
_initData.apply(this,Array.prototype.slice.apply(arguments));
var that = this;
if (that.options.treeView && this.data.length > 0) {
var rows = [];
var roots = $.grep(this.data,function (row,index) {
return row.Level == that.options.treeRootLevel;
});
$.each(roots,item) {
rows.push(item);
var child = getChild(item,that.data,that.options.treeId);
$.each(child,n) {
if (that.options.treeCollapseAll) {
n.hidden = true;
}
rows.push(n);
});
});
that.options.data = that.data = rows;
}
};
//重写bootstrapTable的initPagination方法
BootstrapTable.prototype.initPagination = function () {
//理论情况下,treegrid是不支持分页的,所以默认分页参数为false
this.options.pagination = false;
//调用“父类”的“虚方法”
_initPagination.apply(this,Array.prototype.slice.apply(arguments));
};
//重写bootstrapTable的initBody方法
BootstrapTable.prototype.initBody = function (fixedScroll) {
var that = this,html = [],data = this.getData();
this.trigger('pre-body',data);
this.$body = this.$el.find('tbody');
if (!this.$body.length) {
this.$body = $('').appendTo(this.$el);
}
if (!this.options.pagination || this.options.sidePagination === 'server') {
this.pageFrom = 1;
this.pageTo = data.length;
}
for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
var key,item = data[i],style = {},csses = [],data_ = '',attributes = {},htmlAttributes = [];
if (item.hidden) continue;
style = calculateObjectValue(this.options,this.options.rowStyle,[item,i],style);
if (style && style.css) {
for (key in style.css) {
csses.push(key + ': ' + style.css[key]);
}
}
attributes = calculateObjectValue(this.options,this.options.rowAttributes,attributes);
if (attributes) {
for (key in attributes) {
htmlAttributes.push(sprintf('%s="%s"',key,escapeHTML(attributes[key])));
}
}
if (item._data && !$.isEmptyObject(item._data)) {
$.each(item._data,function (k,v) {
if (k === 'index') {
return;
}
data_ += sprintf(' data-%s="%s"',k,v);
});
}
html.push(''
);
if (this.options.cardView) {
html.push(sprintf('',sprintf('',this.options.iconsPrefix,this.options.icons.detailOpen),'',' Box || column.radio) {
type = column.checkBox ? 'checkBox' : type;
type = column.radio ? 'radio' : type;
text = [that.options.cardView ?
'',id_,class_,data_,rowspan_,title_),indent,icon,value,' tr[data-index] > td').off('click dblclick').on('click dblclick',function (e) {
var $td = $(this),$tr = $td.parent(),item = that.data[$tr.data('index')],index = $td[0].cellIndex,field = that.header.fields[that.options.detailView && !that.options.cardView ? index - 1 : index],field)],field);
if ($td.find('.detail-icon').length) {
return;
}
that.trigger(e.type === 'click' ? 'click-cell' : 'dbl-click-cell',field,$td);
that.trigger(e.type === 'click' ? 'click-row' : 'dbl-click-row',$tr);
if (e.type === 'click' && that.options.clickToSelect && column.clickToSelect) {
var $selectItem = $tr.find(sprintf('[name="%s"]',that.options.selectItemName));
if ($selectItem.length) {
$selectItem[0].click();
}
}
});
this.$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click',function () {
debugger;
var $this = $(this),$tr = $this.parent().parent(),index = $tr.data('index'),row = data[index];
if ($tr.next().is('tr.detail-view')) {
$this.find('i').attr('class',sprintf('%s %s',that.options.iconsPrefix,that.options.icons.detailOpen));
$tr.next().remove();
that.trigger('collapse-row',index,row);
} else {
$this.find('i').attr('class',that.options.icons.detailClose));
$tr.after(sprintf(' tr[data-index] > td > .tree-icon').off('click').on('click',function (e) {
debugger;
e.stopPropagation();
var $this = $(this),row = data[index];
var icon = $(this);
var child = getChild(data[index],data,c) {
$.each(that.data,item) {
if (item[that.options.treeId] == c[that.options.treeId]) {
item.hidden = icon.hasClass(that.options.expandIcon);
that.uncheck(index);
return;
}
});
});
if (icon.hasClass(that.options.expandIcon)) {
icon.removeClass(that.options.expandIcon).addClass(that.options.collapseIcon);
} else {
icon.removeClass(that.options.collapseIcon).addClass(that.options.expandIcon);
}
that.options.data = that.data;
that.initBody(true);
});
this.$selectItem = this.$body.find(sprintf('[name="%s"]',this.options.selectItemName));
this.$selectItem.off('click').on('click',function (event) {
event.stopImmediatePropagation();
var $this = $(this),checked = $this.prop('checked'),row = that.data[$this.data('index')];
if (that.options.maintainSelected && $(this).is(':radio')) {
$.each(that.options.data,row) {
row[that.header.stateField] = false;
});
}
row[that.header.stateField] = checked;
if (that.options.singleSelect) {
that.$selectItem.not(this).each(function () {
that.data[$(this).data('index')][that.header.stateField] = false;
});
that.$selectItem.filter(':checked').not(this).prop('checked',false);
}
that.updateSelected();
that.trigger(checked ? 'check' : 'uncheck',$this);
});
$.each(this.header.events,events) {
if (!events) {
return;
}
if (typeof events === 'string') {
events = calculateObjectValue(null,events);
}
var field = that.header.fields[i],fieldIndex = $.inArray(field,that.getVisibleFields());
if (that.options.detailView && !that.options.cardView) {
fieldIndex += 1;
}
for (var key in events) {
that.$body.find('tr').each(function () {
var $tr = $(this),$td = $tr.find(that.options.cardView ? '.card-view' : 'td').eq(fieldIndex),index = key.indexOf(' '),name = key.substring(0,index),el = key.substring(index + 1),func = events[key];
$td.find(el).off(name).on(name,function (e) {
var index = $tr.data('index'),row = that.data[index],value = row[field];
func.apply(this,[e,index]);
});
});
}
});
this.updateSelected();
this.resetView();
this.trigger('post-body');
};
//给组件增加默认参数列表
$.extend($.fn.bootstrapTable.defaults,{
treeView: false,//treeView视图
treeField: "id",//treeView视图字段
treeId: "id",treeRootLevel: 0,//根节点序号
treeCollapseAll: false,//是否全部展开
collapseIcon: "glyphicon glyphicon-chevron-right",//折叠样式
expandIcon: "glyphicon glyphicon-chevron-down"//展开样式
});
})(jQuery);
Box">','',that.header.formatters[j] && typeof value === 'string' ? value : '',that.options.cardView ? '
' : '',(item.Level - that.options.treeRootLevel) * 15);
var child = $.grep(data,function (d,i) {
return d.ParentId == item[that.options.treeId] && !d.hidden;
});
icon = sprintf('组件的使用如下:
1、首先引用这个js文件。
2、然后初始化组件
treeView:true表示启用树表格模式;
treeId:'Id'表示每一行tree的id;
treeField:'Name'表示要对那一列进行展开;
treeRootLevel:1表示树根的级别。
还有一个地方需要注意,要建立记录之间的父子级关系,必然后有一个ParentId的概念,所以在从后端返回的结果集里面,每条记录势必有一个ParentId的属性,如果是根节点,ParentId为null。比如我们后台得到的结果集的json格式如下:
菜单管理",Url: "/Systems/Menu/Index",ParentId: 1,Level: 2,{Id: 3,Name: "订单管理",CreateTime: "2017-05-31 17:05:27",{Id: 4,Name: "基础数据",CreateTime: "2017-05-31 17:05:55",{Id: 5,Name: "新增订单",Url: "/order/add",ParentId: 3,CreateTime: "2017-05-31 17:07:03",…}]
三、组件需要完善的地方
上述封装给大家提供一个扩展bootstrapTable组件treeview功能,还有很多地方需要完善,比如:
1、我们的叶子节点前面的图标可以去掉;
3、Level字段可以去掉,通过ParentId为null来确定根节点。
有兴趣的小伙伴可以自己试试。
四、总结
至此本文就结束了,这篇针对上篇做了一个补充,使得我们可以根据项目的需求自己选择用哪种方式,如果我们项目使用的是bootstrapTable作为数据展示的组件,可以考虑上述扩展;如果没有使用bootstrapTable,可以试试上篇的组件。