layui table handles wonderful background data and realizes the function of complex header fixed column

The company requires the implementation of complex header tables on mobile phones. The first column can be fixed and other sliding table functions. I have seen that this function is available in elementui, but its multi-level header needs to realize the object relationship between upper and lower levels, and the data returned to us by the background is rendered with colSpan and rowspan, so this plug-in cannot be used.

Then go back to the truth and use the table in the relatively simple layui because its ui is OK.

The complex multi-level header of layui table supports rowspan and colspan.

file: https://www.layui.com/doc/modules/table.html

However, to realize the fixed column function, the file keyword in the header must be bound to the data key. Some, such as jq table and bootstrap table, initialize the header, set the keyword, and then automatically add the data rendering table.

I want to implement such a table (only the template, each header is configured differently), complex header, and the first column is fixed:

The wonderful thing is that when designing the program in the background, the header and data are separated, which means that the header is rendered separately, and then the data part is written in table according to the order:

They are: data, header and table description

 

Data is ordinary key value pair data;

The header is the object given by tr, the content text of each line, and the corresponding Calspan and rowspan

Table description is to tell you the title of the table, and the data order of the table is displayed according to the data of colModel

Although his arrangement is clear and clear, there is no problem rendering the header and table body separately, but I want to use layui table to fix the complex header and column. The header must be bound with the data key, and the messy colSpan and rowspan given by the header are very troublesome to deal with. It takes a lot of brain cells to make it clear.

Start processing data on the front end:

First of all, we should make it clear that those with colspan of 1 generally need to bind the data display, but the order of the header of multiple rows with colspan of 1 in the data cannot be determined, so we can't bind key s for them in order. At this time, I thought of using placeholders to make the total number of objects in each row the same

First look at the original data:

//Loop header data
				for(var i=0;i<headers.length;i++){
					var array=[];
					var header1=headers[i].colomnVos;
					//console.log(header1)
					//Cycle the data in each column header
					for(var j=0;j<header1.length;j++){
						var obj={}
						//At this time, it is only the prototype of the construction object, and the field cannot be bound
						obj={
							title:header1[j].name,
							rowspan:header1[j].rowspan,
							colspan:header1[j].colspan,
							style:{height:'auto'},
							align:'center',
							fake:false
						}
						array.push(obj)
						//Key: if colspan is not 1, add several placeholder objects after it
						if(header1[j].colspan!=1){
							var thisColspan=header1[j].colspan;
							for(var k=1;k<thisColspan;k++){
								obj={
									fake:true
								}
								array.push(obj)
							}
							
						}
					}
					tableCols.push(array);
				}
				//Print what this stage looks like
				var fuzhi=JSON.stringify(tableCols);
				var fuzhi1=JSON.parse(fuzhi)
				console.log(fuzhi1)

Take another look at the processed data:

At this time, it is found that placeholder objects have been inserted, but the total number of objects in each row is still different, because some header rowspan has a certain value of 1

For example, the city column directly spans three rows. Even if you expand all rowspans and add placeholder objects, there will be one less object. Therefore, in addition to rowspan, you also need to consider the problem of colspan.

At present, the header of the first row can be determined. In any case, rowspan does not need to be considered. Expanding all colspan must represent the maximum number of columns in the table. Then I can start the vertical cycle with the maximum number of columns. If the upper level header rowspan is not 1, a placeholder object is also inserted in the lower rowspan level header. It is difficult to describe, so I can directly use the code:

//Starting from the first vertical loop, maxHeaderLength is the maximum number of columns obtained from the table data
				for(var i=0;i<maxHeaderLength;i++){
					for(var j=0;j<tableCols.length;j++){
						var header1=tableCols[j];
						if(!!header1[i]){
							//At this time, it can be judged that all with colspan of 1 have their own data and bind field s for them
							if(header1[i].colspan==1){
								if(i==0){
									header1[i].field=pageConfVo[i];
									header1[i].fixed='left'
								}else{
									header1[i].field=pageConfVo[i];
								}
							}
							//Key: if rowspan is not 1, insert a placeholder in the following header
							if(header1[i].rowspan>1){
								for(var k=0;k<header1[i].rowspan-1;k++){
									tableCols[j+k+1].splice(i, 0, {fake:true});
								}
							}
						}
					}
				}
				var aaa=JSON.stringify(tableCols)
				console.log(JSON.parse(aaa))

Now, look at the data:

This is done. It can ensure that the column corresponding to colspan of 1 is unique in each row header, so they can be assigned field directly.

After the assignment, of course, the useless placeholder objects should be deleted:

//last
				for(var i=0;i<tableCols.length;i++){
					var header2=tableCols[i];
					
					for(var j=0;j<header2.length;j++){
						if(header2[j].fake){
							header2.splice(j--,1);
						}
					}
				}
				console.log(tableCols)

Final results:

It returns to the original state, but the difference is that the columns of the bound data key are bound.

It's not easy. Stick down the complete code:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Layui</title>
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <link rel="stylesheet" href="../lib/layui/css/layui.css"  media="all">
  <script src="../js/ipAddress.js" type="text/javascript" charset="utf-8"></script>
  <!-- Note: if you copy all the code directly to the local, the above css The path needs to be changed to your local path -->
  <style type="text/css">
  	#title{
		font-size:16px;
		font-weight:bold;
		text-align: center;
		line-height: 30px;
		padding:10px
	}
	.layui-table-header{
		
	}
	.shuoming{
		line-height: 26px;
		background: #E8F4FF;
		border-bottom:1px solid #ddd;
		padding:10px;
		font-size:13px
	}
	.shuoming .s1{
		color:white;
		background:#439FFF;
		display: inline-block;
		padding:0 10px;
		border-radius: 10px;
		margin-right:10px;
	}
	thead .layui-table-cell{
		height:40px !important;
		white-space:normal;
		padding:0;
	}
	.span{
		
	}
	.tip{
		line-height:60px;
		color:#aaa;
		font-size:16px;
		text-align: center;
		display: none;
	}
  </style>
</head>
<body>
	<div class="shuoming">
		<span class="s1">Indicator description</span>
		<span>For the index caliber, please refer to the index description issued by Cui Yan of the marketing department. If you have any questions or suggestions on the index, please contact Cui Yan of the marketing department or Chen Zhe of the industry branch.</span>
	</div>
	<div id="title">
		
	</div>
	<table id="demo" lay-filter="test"></table>
	<div class="tip">
		No data
	</div>
               
<script src="../js/jquery-3.3.1.min.js" type="text/javascript" charset="utf-8"></script>          
<script src="../lib/layui/layui.js" charset="utf-8"></script>
<!-- Note: if you directly copy all the code to the local, the above JS The path needs to be changed to your local path -->
<script>
	var table
    var tableCols=[];
	var height=0;
	var qryDate="";
	var sign="";
	var areaCode="";
	var tableCode="";
	var type="";
	//Split number of tables
	var maxHeaderLength=0;
	//Header text length
	var maxTextLength=0;
	//var url=baseUrl+'tongbao/getTongBaoDataJson.action';
	var url='../static/data.json';
	
	$(function(){
		var args=getQueryStringArgs();
		qryDate=args.qryDate;
		sign=args.sign;
		areaCode=args.areaCode;
		tableCode=args.tableCode;
		type=args.type;
		
		$.ajax({
			type: 'get',
			url: url,
			data:{
				qryDate:qryDate,
				sign:sign,
				areaCode:areaCode,
				tableCode:tableCode,
				type:type
			},
			dataType: 'json',
			async:false,
			success: function(res){
				console.log(res)
				if(res.data.length==0){
					$(".tip").show();
				}
				var data =res.data[0];
				var headers=data.headThVos;
				var pageConfVo= data.pageConfVo.colModels;
				maxHeaderLength=parseInt(data.pageConfVo.colCount);
				$("#title").html(data.pageConfVo.cTitle)
				
				//Loop header data
				for(var i=0;i<headers.length;i++){
					var array=[];
					var header1=headers[i].colomnVos;
					//console.log(header1)
					//Cycle the data in each column header
					for(var j=0;j<header1.length;j++){
						var obj={}
						if(header1[j].name.length>maxTextLength){
							maxTextLength=header1[j].name.length;
						}
						//At this time, it is only the prototype of the construction object, and the field cannot be bound
						obj={
							title:header1[j].name,
							rowspan:header1[j].rowspan,
							colspan:header1[j].colspan,
							style:{height:'auto'},
							align:'center',
							fake:false
						}
						array.push(obj)
						//Key: if colspan is not 1, add several placeholder objects after it
						if(header1[j].colspan!=1){
							var thisColspan=header1[j].colspan;
							for(var k=1;k<thisColspan;k++){
								obj={
									fake:true
								}
								array.push(obj)
							}
							
						}
					}
					tableCols.push(array);
				}
				//Print what this stage looks like
				var fuzhi=JSON.stringify(tableCols);
				var fuzhi1=JSON.parse(fuzhi)
				console.log(fuzhi1)
				//Starting from the first vertical loop, maxHeaderLength is the maximum number of columns obtained from the table data
				for(var i=0;i<maxHeaderLength;i++){
					for(var j=0;j<tableCols.length;j++){
						var header1=tableCols[j];
						if(!!header1[i]){
							//At this time, it can be judged that all with colspan of 1 have their own data and bind field s for them
							if(header1[i].colspan==1){
								if(i==0){
									header1[i].field=pageConfVo[i];
									header1[i].fixed='left'
								}else{
									header1[i].field=pageConfVo[i];
								}
							}
							//Key: if rowspan is not 1, insert a placeholder in the following header
							if(header1[i].rowspan>1){
								for(var k=0;k<header1[i].rowspan-1;k++){
									tableCols[j+k+1].splice(i, 0, {fake:true});
								}
							}
						}
					}
				}
				var aaa=JSON.stringify(tableCols)
				console.log(JSON.parse(aaa))
				//last
				for(var i=0;i<tableCols.length;i++){
					var header2=tableCols[i];
					
					for(var j=0;j<header2.length;j++){
						if(header2[j].fake){
							header2.splice(j--,1);
						}
					}
				}
				console.log(tableCols)
			},
			error:function(data) {
				//console.log(data.msg);
			},
		});	
	})
	
	layui.use('table', function(){
	  table = layui.table;
	  //console.log(height)
	  //First instance
	  table.render({
		  id:"itest",
		  where: {
				qryDate:qryDate,
				sign:sign,
				areaCode:areaCode,
				tableCode:tableCode,
				type:type
			},
		elem: '#demo',
		size: 'sm',
		//,height: height
		url: url ,//data interface 
		parseData: function(res){ //res is the original returned data
			//console.log(res)
			var data=res.data[0];
			var count=data.contents.length;
			var data1=data.contents;
			//console.log(height)
			
		    return {
		      "code": res.code, //Resolve interface status
		      "msg": res.msg, //Parse prompt text
		      "count": count, //Parse data length
		      "data": data1 //Parse data list
		    };
		},
		page: false, //Open paging
		cols: tableCols,
		cellMinWidth:100,
		done: function(res, curr, count){
		    //If you request data asynchronously, res is the information returned by your interface.
		    //If it is a direct assignment method, res is: {data: [], count: 99} data is the data of the current page, and count is the total length of the data
		    console.log(res);
		    
		    //Get current page number
		    console.log(curr); 
		    
		    //Total data obtained
		    console.log(count);
			
			console.log(maxTextLength)
			if(maxTextLength>16){
				$("thead .layui-table-cell").css("fontSize",'10px')
			}
		  },
		  error:function(){
			  
		  }
	  });
	  
	});
	
	
	/* window.onresize = () => {
	  return (() => {
		 if(document.documentElement.clientHeight>document.documentElement.clientWidth){
			  that.titleHeight=50;
		  }else{
			  that.titleHeight=40;
		  }
		window.screenHeight = document.documentElement.clientHeight
		height = window.screenHeight-250;
		//console.log(window.screenHeight)
		//console.log(height)
		//table.resize('itest');
		table.reload('itest', {}, false)
	  })() 
	}*/
	
	function getQueryStringArgs() {
		//Get the query string and remove the question mark at the beginning
		var qs = (location.search.length > 0 ? location.search.substring(1) : ""),
	
			//Object to save data
			args = {},
	
			//Get every item
			items = qs.length ? qs.split("&") : [],
			item = null,
			name = null,
			value = null,
			//Use in a for loop
			i = 0,
			len = items.length;
		//Add each item to the args object one by one
		for(i = 0; i < len; i++) {
			item = items[i].split("=");
				name = decodeURIComponent(item[0]);
				value = decodeURIComponent(item[1]);
				if(name.length) {
					args[name] = value;
				}
			}
		
			return args;
	}
</script>

</body>
</html>

 

Keywords: Javascript Front-end JQuery html

Added by blinks on Fri, 21 Jan 2022 20:09:56 +0200