[Extjs]创建FormTableLayout布局器

介绍了一种结合 ExtJS 的 FormLayout 和 TableLayout 特性的 FormTableLayout 插件,该插件支持自由的表格布局,允许指定单元格显示内容及位置,适用于复杂的表单布局需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原创,转载请标明出处。
Extjs自带的FormLayout布局若要使用多列,需要自己做tpl或者使用HTML+renderTo,很麻烦。而TableLyout只支持Flow排列,且用于FormPanel中不能正确显示Label,等等,两者皆不适合自由的table+form布局需求。FormTablLayout解决该问题。
 
My.layout.FormTableLayout = FormLayout + TableLayout
 
增强项:可指定显示位置…..
使用方法:适用于FormLayout/TableLayout所适用场合,指定layoutformtable即可。
 
1) 基本功能:
a)        指定表格列数(行数将根据内容自动添加)
b)        横、纵向融合
c)        一个单元格内容
d)        在一个单元格中显示多项内容
e)        指定显示位置
f)          支持显示form field
g)        单元格内容显示模板可设置
2) 使用范例
    varitems=[
    {
       html:'横向融合',
       row:3,
       col:0,
       colspan:2 
    },{
       html:'-------我的地盘--------',
       row:2,
       col:1     
    },{
       html:'========我也来===========',
       row:2,
       col:1     
}……
 
    vartableForm=newExt.FormPanel({
       layout:'formtable',//使用FormTableLayout
       style:'height:100%',
       title:'TableForm',
       items:items
    });
 
3) 效果
/**
 * @class My.ui.FormTableLayout
 * @extends Ext.layout.ContainerLayout
 * @author zfzheng
 * 
 * 
 * 
 * FormTableLayout= FormLayout + TableLayout
 * 
 * 适用于FormLayout/TableLayout适用的场合。
 * 除拥有FormLayout/TableLayout特征外,还具有指定单元格显示功能:
 *   设置autoFlow为true,根据items项的row/col属性定位单元格排列。
 *   可以在同一单元格内显示多项item(指定row/col)为同一位置即可,按在原数组中的顺序排列。
 *   注:
 *    1)若autoFlow为true,items项没有row或col属性的均不被显示。
 *    2)若某item的row/col设置在被融合了的单元格位置,则该项不被显示。
 * 
  var items=[
 {
  html:'横向融合',
  row:3,
  col:0,
  colspan:2 
 },{
  html:'-------我的地盘--------',
  row:2,
  col:1  
 },{
  html:'========我也来===========',
  row:2,
  col:1  
 },{
  html:'~~~~~~~~~真挤啊~~~~~~~~~~',
  row:2,
  col:1
 },{
  html:'非第一单元格起填充',
  row:0,
  col:1  
 },{
  html:'纵向融合',
  row:1,
  col:0,
  rowspan:2 
 },{
  html:'Hello,how are you?正常Cell',
  row:1,
  col:1  
 },{
  name:'count',
  fieldLabel:'件数',
  value:'1',
  xtype:'numberfield',
  row:4,
  col:0  
 },{
  name:'logTime',
  fieldLabel:'编制日期',
  value:'',
  xtype:'datefield',
  row:4,
  col:1  
 }  
 ]
 
 var tableForm=new Ext.FormPanel({
  layout: 'formtable', //使用FormTableLayout
  style: 'height:100%',
  title: 'Table Form',
  items: items
 });
 
 tableForm.renderTo(Ext.getBody());
 * 
 * 
 
*/
My.layout.FormTableLayout
=Ext.extend(Ext.layout.ContainerLayout,{
 
// private
 monitorResize:false,
 
 
/**
  * Table列数
  
*/
 columns:
2
 
/**
  * 是否自动排列
  *  若为true,则按行方向自动排列。
  *  若为false,则根据item指定的[row,col]排列,无row/col属性的项被忽略显示。
  
*/
 autoFlow:
false,
 
/**
  * Form Element显示模板
  
*/
 fieldTpl:
     
new Ext.Template(
        
'<div class="x-form-item {5}" tabIndex="-1">',
            
'<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
            
'<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
            
'</div><div class="{6}"></div>',
        
'</div>'
    ),
    
 
/**
  * 普通内容(非Form Element)显示模板
  
*/    
    cellContentTpl:
new Ext.Template('<div class="x-form-item-label">{0}</div>'),
    
    
// private
    setContainer : function(ct){
        My.layout.FormTableLayout.superclass.setContainer.call(
this, ct);
        
this.currentRow = 0;
        
this.currentColumn = 0;
        
this.spanCells = [];
        
this.maxCreatedRowIndex=-1;
    },    
    
    
// private
 onLayout : function(ct, target){
     
var cs = ct.items.items, len = cs.length;
     
if(!this.table){
         
//target.addClass('x-table-layout-ct');
         this.table = target.createChild(
             {tag:
'table', cls:'x-table-layout', border:1, cellspacing:3, cn: {tag: 'tbody'}}, nulltrue);
   
         
if(!this.autoFlow){
          
var items=[];
          
for(var i=0;i<len;i++){
           
//如果设置了autoFlow为true,则无row、col属性的字段将无法显示。
           if(typeof cs[i].row!='undefined' && typeof cs[i].col!='undefined'){
            cs[i].__index
=i;
      items.push(cs[i]);
           }
          }
          ct.items.items
=items.sort(function(item1,item2){
           
if(item1.row==item2.row){
            
if(item1.col==item2.col){
             
return item1.__index-item2.__index;
            }
            
return item1.col-item2.col;
           }
           
return item1.row-item2.row;
          });
         }
         
this.renderAll(ct, target);
     }
 },
 
    
// private
    createRow : function(index){
        
var row = this.table.tBodies[0].childNodes[index];
        
if(!row){
            row 
= document.createElement('tr');
            
this.table.tBodies[0].appendChild(row);
            
this.maxCreatedRowIndex=Math.max(this.maxCreatedRowIndex,index);
        }
        
return row;
    },
        
    
// private
 getRow : function(index){
  
if(!this.autoFlow){
   
//确保创建index之前的row
   for(var i=Math.max(0,this.maxCreatedRowIndex+1);i<index;i++){
    
this.createRow(i);
   } 
  }
  
return this.createRow(index);
 },
 
 
// private
 getCellAt : function(c,row,col){
  
if(this.spanCells[col] && this.spanCells[col][row]){
   
return null;
  }
  
//计算之前有多少spanCells
  var spanCount=0;  
  
for(var i=0;i<col;i++){
   
if(this.spanCells[i] && this.spanCells[i][row]){
    spanCount
++;
   }   
  }
  
var r=this.getRow(row);
  
var cell=r.childNodes[col-spanCount];
  
if(cell){
   
return cell;
  }
  
this.currentRow=row;
  
//预设置nextCell之前的初始列索引
  this.currentColumn=spanCount-1;
  
for(var i=spanCount;i<=col;i++){
   
this.getNextCell(c);
  }
  
return r.childNodes[col-spanCount];
 },
 
    
// private
 getNextCell : function(c){
        
var td = document.createElement('td'), row, colIndex;
        
if(!this.columns){
            row 
= this.getRow(0);
        }
else {
         colIndex 
= this.currentColumn;
            
if(colIndex !== 0 && (colIndex % this.columns === 0)){
                
this.currentRow++;
                colIndex 
= (c.colspan || 1);
            }
else{
                colIndex 
+= (c.colspan || 1);
            }
            
            
//advance to the next non-spanning row/col position
            var cell = this.getNextNonSpan(colIndex, this.currentRow);
            
this.currentColumn = cell[0];
            
if(cell[1!= this.currentRow){
             
this.currentRow = cell[1];
             
if(c.colspan){
              
this.currentColumn += c.colspan - 1;
             }
            }
            row 
= this.getRow(this.currentRow);
        }
        
if(c.colspan){
            td.colSpan 
= c.colspan;
        }
  td.className 
= 'x-table-layout-cell';
        
if(c.rowspan){
            td.rowSpan 
= c.rowspan;
   
var rowIndex = this.currentRow, colspan = c.colspan || 1;
   
//track rowspanned cells to add to the column index during the next call to getNextCell
   for(var r = rowIndex+1; r < rowIndex+c.rowspan; r++){
    
for(var col=this.currentColumn-colspan+1; col <= this.currentColumn; col++){
     
if(!this.spanCells[col]){
      
this.spanCells[col] = [];
     }
     
this.spanCells[col][r] = 1;
    }
   }
        }
        row.appendChild(td);
        
return td;
    },
    
    
// private
    getNextNonSpan: function(colIndex, rowIndex){
     
var c = (colIndex <= this.columns ? colIndex : this.columns), r = rowIndex;
        
for(var i=c; i <= this.columns; i++){
         
if(this.spanCells[i] && this.spanCells[i][r]){
          
if(++> this.columns){
           
//exceeded column count, so reset to the start of the next row
                 return this.getNextNonSpan(1++r);
          }
         }
else{
          
break;
         }
        }
        
return [c,r];
    },
    
 
// private
    renderItem : function(c, position, target){
     
//target is form or other container
     if(c && !c.rendered ){
      
var td=this.autoFlow?this.getNextCell(c):this.getCellAt(c,c.row,c.col);
      
if(!td){
       
//cell at[row,col] is spanCell,不渲染。(row,col设置不正确)
       return;
      }
         
if(c.isFormField && c.inputType != 'hidden'){
             
var args = [
                    c.id, c.fieldLabel,
                    c.labelStyle
||this.labelStyle||'',
                    
this.elementStyle||'',
                    
typeof c.labelSeparator == 'undefined' ? this.labelSeparator : c.labelSeparator,
                    (c.itemCls
||this.container.itemCls||''+ (c.hideLabel ? ' x-hide-label' : ''),
                    c.clearCls 
|| 'x-form-clear-left' 
             ];
             
if(typeof position == 'number'){
                 position 
= target.dom.childNodes[position] || null;
             }
             
if(position){
              
//this.fieldTpl.insertBefore(position, args);
                 this.fieldTpl.append(td, args);
             }
else{
                 
//this.fieldTpl.append(target, args);
              this.fieldTpl.append(td, args);
             }
             c.render(
'x-form-el-'+c.id);
         }
else {
             
//My.layout.FormTableLayout.superclass.renderItem.apply(this, arguments);
             this.cellContentTpl.append(td,[c.text||c.html||c.value]);
         }
        }
    },
    
    
// private
    isValidParent : function(c, target){
        
return true;
    }    
});
Ext.Container.LAYOUTS[
'formtable'= My.layout.FormTableLayout;
 
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值