• Extjs4中的常用组件:Grid、Tree和Form


    至此我们已经学习了Data包和布局等API。下面我们来学习作为Extjs框架中我们用得最多的用来展现数据的Grid、Tree和Form吧!
    目录:
     
    5.1. Grid panel                                          
         Grid应该是我们在开发时使用的最多的组件之一。Extjs4对其进行了重大的改进。
         Extjs4与Extjs3的Grid生成不同的HTML。Sencha称其为智能渲染(Intelligent Rendering)。Extjs3中即使不需要Grid的所有特性,它也会生成整套HTML。而Extjs4就只会渲染Grid所用到的特性,这样就使渲染最小化且提高了性能。
         在学习Extjs4中Grid的新特性前,让我们先了解在Extjs4中如何创建一个简单的Grid吧!
    Ext.create("Ext.grid.Panel", {
         store: Ext.create("Ext.data.ArrayStore", {
              fields: [{name: "book", name: "author"}],
              data: [["Ext  JS 4: First Look", "Loiane Groner"]]
         }),
         columns: [{
              text: "Book",
              flex: 1,
              sortable: false,
              dataIndex: "book"
         },{
              text: "Author",
              100,
              sortable: true,
              dataIndex: "author"
         }],
         height: 80,
         widht: 300,
         title: "Simple Grid",
         renderTo: Ext.getBody()
    });
    通过上述的代码片段,我们可以知道Extjs4和Extjs3在创建简单Grid时是无差别的。
     
    5.1.1. Columns                                            
         Extjs4中将Grid的column类归纳到一个独立的Ext.grid.column包中。
         现在我们一起学习各类型的column吧。
         首先定义Model类和Store并加载示例数据:
         Ext.define('Book', {

    extend: 'Ext.data.Model',

    fields: [

    {name: 'book'},

    {name: 'topic', type: 'string'},

    {name: 'version', type: 'string'},

    {name: 'released', type: 'boolean'},

    {name: 'releasedDate', type: 'date'},

    {name: 'value', type: 'number'}

    ]

    });

    var store = Ext.create('Ext.data.ArrayStore', {

    model: 'Book',

    data: [

    ['Ext JS 4: First Look','Ext JS','4',false,null,0],

    ['Learning Ext JS 3.2','Ext JS','3.2',tr ue,'2010/10/01',40.49],

    ['Ext JS 3.0 Cookbook','Ext JS','3',true,'2009/10/01',44.99],

    ['Learning Ext JS','Ext JS','2.x',true,'2008/11/01',35.99],

    ]

    });  
     
    然后就是创建Grid了:
    Ext.create('Ext.grid.Panel', {
    store: store,
    550,
    title: 'Ext JS Books',
    renderTo: 'grid-example',
    selModel: Ext.create('Ext.selection.CheckboxModel'), //1
    columns: [
    Ext.create('Ext.grid.RowNumberer'), //2
    {
    text: 'Book',//3
    flex: 1,
    dataIndex: 'book'
    },{

    text: 'Category', //4

    xtype:'templatecolumn',

    100,

    tpl: '{topic} {version}'

    },{

    text: 'Already Released?', //5

    xtype: 'booleancolumn',

    100,

    dataIndex: 'released',

    trueText: 'Yes',

    falseText: 'No'

    },{

    text: 'Released Date', //6

    xtype:'datecolumn',

    100,

    dataIndex: 'releasedDate',

    format:'m-Y'

    },{

    text: 'Price', //7

    xtype:'numbercolumn',

    80,

    dataIndex: 'value',

    renderer: Ext.util.Format.usMoney

    },{

    xtype:'actioncolumn', //8

    50,

    items: [{

    icon: 'images/edit.png',

    tooltip: 'Edit',

    handler: function(grid, rowIndex, colIndex) {

    var rec = grid.getStore().getAt(rowIndex);

    Ext.MessageBox.alert('Edit',rec.get('book'));

    }

    },{

    icon: 'images/delete.gif',

    tooltip: 'Delete',

    handler: function(grid, rowIndex, colIndex) {

    var rec = grid.getStore().getAt(rowIndex);

    Ext.MessageBox.alert('Delete',rec.get('book'));

    }

    }]

    }]

     
    });
    效果如下:
    1. 通过selModel配置项设置选择模式,具体有三种选择模式:RowModel、CellModel和CheckboxModel,其中CheckboxModel会自动插入Checkbox列作为Grid的第一列;
    2. 在配置columns时我们创建了一个序号列(Ext.create("Ext.panel.RowNumberer"));
    3. Book列没有指定列类型,那么默认以string数据类型来展现数据;
    4. Category列指定列类型为templatecolumn,就是说可以通过tpl属性来设置该列数据呈现的样式。tpl属性为string数据类型,可通过{Model实例中name}的形式来访问记录中任意的字段值;
    5. Already Released?列指定列类型为booleancolumn,就是说该列对应的Model实例属性值为boolean类型,而且我们可以通过trueText和falseText来设置值为真/假时分别呈现什么内容;
    6. Released Date列指定列类型为datecolumn,并通过format属性来设置以某种格式来呈现日期信息;
    7. Price列指定列类型为numbercolumn,而这里通过设置renderer:Ext.util.Format.usMoney来设置该列的呈现样式。renderer属性是从Column类(所有Column类型的父类)继承得到的,所以各个column类均可设置该属性,属性值为function(value){........; return "呈现的内容";},参数value为该单元格中对应的Model实例的属性值。而Ext.util.Format.usMoney是内置的格式化函数,当然我们可以自定义Ext.util.Format.rmbMoney的函数啦;
    8. 最后一列没有表头并指定列类型为actioncolumn,该列用于添加行级的增、删、查、改等操作按钮。
     
     
    5.1.2. Feature                                        
         如果我们想在Extjs3中为grid添加新功能,我们一般要创建或扩展GridPanel类。但官方没有提供一种统一的方式去处理这个问题。在Extjs4中我们可以通过继承Ext.grid.feature.Feature(类中含有公用方法和属性)来实现上述的需求。(译者语:具体如何定义Ext.grid.feature.Feature子类,我还没试过)
         在Ext.grid.feature包中有7个类:AbstractSummary,Chunking,Feature,Grouping,GroupingSummary,RowBody和Summary。
         下面我们来学习如何使用feature,具体如下
         features:[{
              groupHeaderTpl: "Publisher: {name}",
              ftype: "groupingsummary"
         }]
     
    5.1.2.1. Ext.grid.feature.Grouping                                  
         直接上代码吧!

    Ext.define('Book', {

    extend: 'Ext.data.Model',

    fields: ['name', 'topic']

    });

    var Books = Ext.create('Ext.data.Store', {

    model: 'Book',

    groupField: 'topic',

    data: [{

    name: 'Learning Ext JS',

    topic: 'Ext JS'

    },{

    name: 'Learning Ext JS 3.2',

    topic: 'Ext JS'

    },{

    name: 'Ext JS 3.0 Cookbook',

    topic: 'Ext JS'

    },{

     
    name: 'Expert PHP 5 Tools',

    topic: 'PHP'

    },{

    name: 'NetBeans IDE 7 Cookbook',

    topic: 'Java'

    },{

    name: 'iReport 3.7',

    topic: 'Java'

    },{

    name: 'Python Multimedia',

    topic: 'Python'

    },{

    name: 'NHibernate 3.0 Cookbook',

    topic: '.NET'

    },{

    name: 'ASP.NET MVC 2 Cookbook',

    topic: '.NET'

    }]

    });

    Ext.create('Ext.grid.Panel', {

    renderTo: Ext.getBody(),

    frame: true,

    store: Books,

    350,

    height: 400,

    title: 'Books',

    features: [Ext.create('Ext.grid.feature.Grouping',{

    groupHeaderTpl: 'topic: {name} ({rows.length} Book{[values.rows.length > 1 ? "s" : ""]})'

    })],

    columns: [{

    text: 'Name',

    flex: 1,

    dataIndex: 'name'

    },{

    text: 'Topic',

    flex: 1,

    dataIndex: 'topic'

    }]

     
    });
     
    通过上面的代码片段,我们可以看到要使用Ext.grid.feature.Grouping还要在Store中设置groupField属性来设置分组字段名。然后通过groupHeaderTpl属性来设置分组头,{name}就是访问groupField指向的字段的值,{rows.length}就是组记录数目。
     
    5.1.2.2. Ext.grid.feature.Summary                                            
         Ext.grid.feature.Summary实在Grid所有记录行的最后插入总结行。该类继承于Ext.grid.feature.AbstractSummary类。

    Ext.create('Ext.grid.Panel', {

    renderTo: Ext.getBody(),

    frame: true,

    store: Books,

    350,

    height: 300,

    title: 'Books',

    features: [{

    ftype: 'summary'

    }],

    columns: [{

    text: 'Name',

    flex: 1,

    dataIndex: 'name',

    summaryType: 'count',

    summaryRenderer: function(value){

    return Ext.String.format('{0} book{1}',

    value, value !== 1 ? 's' : '');

    }

    },{

    text: 'Topic',

    flex: 1,

    dataIndex: 'topic'

    }]

    }); 

    从上述代码片段可知道,features配置项中我们只需配置{ftype: "summary"},然后在需要作归纳总结的列中配置summaryType和summaryRenderer即可(也就是说,不配置这两项,那么该列将不出现归纳总结的内容)。
    summaryType: 内置值有count,average,sum,min,max,可以赋形式为function(records){return "输出内容";}的方法,参数records为model实例数组;
    summaryRenderer: 用于设置总结列的呈现样式,可赋形式为function(value, summaryValue, field){return "呈现内容";}的方法,参数value是归纳总结后的值(就是经过summaryType处理后的值),参数summaryValue是所有的记录,参数field是Model实例的当前总结列的列名。
    效果如下:
     
    5.1.2.3. Ext.grid.feature.GroupingSummary                              
         Ext.grid.feature.GroupingSummary是在Ext.grid.feature.Grouping和Ext.grid.feature.Summary的基础上,为每一个分组添加了一行总结行。具体代码如下:

    Ext.create('Ext.grid.Panel', {

    renderTo: Ext.getBody(),

    frame: true,

    store: Books,

    350,

    height: 400,

    title: 'Books',

    features: [{

    groupHeaderTpl: 'Topic: {name}',

    ftype: 'groupingsummary'

    }],

    columns: [{

    text: 'Name',

    flex: 1,

    dataIndex: 'name',

    summaryType: 'count',

    summaryRenderer: function(value){

    return Ext.String.format('{0} book{1}',

    value, value !== 1 ? 's' : '');

    }

    },{

    text: 'Topic',

    flex: 1,

    dataIndex: 'topic'

    }]

     
    }); 
     
    5.1.2.4. Ext.grid.feature.RowBody                                      
         该特性会在每行的底部插入一个<tr><td><div></div></td></tr>,供我们现实额外的信息。
    Ext.create('Ext.grid.Panel', {
    renderTo: Ext.getBody(),
    frame: true,
    store: Books,
    350,
    height: 300,
    title: 'Books',
    features: [{
    ftype: 'rowbody',
    getAdditionalData: function(data, idx, record, orig) {
    return {
    rowBody: Ext.String.format(
    '<div>->topic:<span> {0}</span></div>',
    data.topic)
    };
    }
    }],

    columns: [{

    text: 'Name',

    flex: 1,

    dataIndex: 'name'

    }]

     
    }); 
    使用了rowBody特性后必须要定义getAdditionalData属性,否则rowBody将不起作用。getAdditionalData值为形如
    function(data, rowIndex, record, orig){
         ........ 
         return {
              rowBody: "额外信息的展现HTML标签",
              rowBodyCls: "额外信息的展现的CSS样式",
              rowBodyColspan: 合并列数
         };
    },其中参数data为为该行的数据,参数rowIndex为行索引,参数record为该行的model对象,参数orig代表原始的消息对象。
    注意:当设置了rowBody特性后,Grid对象会有rowbodyclick、rowbodydbclick和rowbodycontextmenu三个事件可供订阅。
     
    5.1.3. Grid Plugins                                          
         Extjs4中引入了plugin包,其中包含Editing、CellEditing、RowEditing、HeaderResizing和DragDrop五个类。Editing类是一个提供通用方法和属性给可编辑Grid的抽象类。CellEditing和RowEditing是Editing的子类。
    (译者语:本人对于features和plugins的理解是,两者都是Grid的插件,但features与Grid的耦合性更大,如Summary Feature会直接影响到Grid的Columns的配置;而plugins与Grid的耦合性较小,是在Grid上再加一层外衣,不用修改Grid的配置)
    (译者语:对于Grid Plugins这一章本人并没有太多实践经验,因为在开发lppExt(一个搭建在Extjs框架之上,旨在更高效地开发各种管理系统的框架)时为求通用性很少采用Grid Plugins,本节内容均以原文内容为主)
     
    5.1.3.1. Ext.grid.plugin.CellEditing                              
         CellEditing插件可以让我们编辑Grid中特定的单元格。但我们点击某个可编辑的单元格时,就会呈现编辑器(editor)并供我们编辑单元格的值。
    下面是实例:
    Ext.define('Contact', {
    extend: 'Ext.data.Model',
    fields: ['name', 'email','phone']
    });
    var Contacts = Ext.create('Ext.data.Store', {
    model: 'Contact',
    data: [
    {name: 'Loiane', email: 'me@loiane.com', phone: '1234-5678'},
    {name: 'Peter', email: 'peter@email.com', phone: '2222-2222'},
    {name: 'Ane', email: 'ane@email.com', phone: '3333-3333'},
    {name: 'Harry', email: 'harry@email.com', phone: '4444-4444'},
    {name: 'Camile', email: 'camile@email.com', phone: '5555-5555'}
    ]
    });
     
     

    Ext.create('Ext.grid.Panel', {

    renderTo: Ext.getBody(),

    frame: true,

    store: Contacts,

    350,

    title: 'Contacts',

    selType: 'cellmodel',

    columns: [{

    text: 'Name',

    flex: 1,

    dataIndex: 'name'

     
    },{

    text: 'Email',

    flex: 1,

    dataIndex: 'email',

    editor: {

    xtype:'textfield',

    allowBlank:false

    }

    },{

    text: 'Phone',

    flex: 1,

    dataIndex: 'phone',

    editor: {

    xtype:'textfield',

    allowBlank:false

    }

    }],

    plugins: [

    Ext.create('Ext.grid.plugin.CellEditing', {

    clicksToEdit: 1

    })

    ]

     
    });
    上述代码中,我们需要注意下列几点:
    1. 除了plugins属性设置为CellEditing外,我们还要设置clicksToEdit属性。clicksToEdit属性表示用户点击单元格多少次会进入编辑模式;
    2. 要通过配置columns属性中各列的editor属性来决定该列是否为可编辑列,editor的值类型为Ext.form.field.Field。只有配置了editor属性的列,在点击其单元格时才可进入编辑模式;
    3. 另外我们还要配置selType为cellModel,从而使选择模式改为可选择单元格。该属性默认为rowModel,选择模式为选择一整行。
     
    5.1.3.2. Ext.grid.plugins.RowEditing                                    
         RowEditing插件让我们可对特定的行进行编辑。但我们点击某一行时,该行就转换为编辑模式了。
    代码如下:

    Ext.create('Ext.grid.Panel', {

    renderTo: Ext.getBody(),

    frame: true,

    store: Contacts,

    350,

    title: 'Contacts',

    selType: 'rowmodel',

    columns: [{

    text: 'Name',

    flex: 1,

    dataIndex: 'name'

    },{

    text: 'Email',

    flex: 1,

    dataIndex: 'email',

    editor: {

    xtype:'textfield',

    allowBlank:false

    }

    },{

    text: 'Phone',

    flex: 1,

    dataIndex: 'phone',

    editor: {

    xtype:'textfield',

    allowBlank:false

     
    }

    }],

    plugins: [

    Ext.create('Ext.grid.plugin.RowEditing', {

    clicksToEdit: 1

    })

    ]

     
    }); 
    与CellEditing一样,我们也要设置clicksToEdit属性。而且要为可编辑列配置editor属性。而selType要设置为rowModel
     
    5.1.3.3. 保存数据到服务器端                                           
         为了将操作结果保存到服务器端,我们需要修改Store来支持CRUD操作,具体代码如下:

    var Contacts = Ext.create('Ext.data.Store', {

    model: 'Contact',

    proxy: {

    type: 'ajax',

    api: {

    read : 'contact/view.php',

     
    create : 'contact/create.php',

    update: 'contact/update.php',

    destroy: 'contact/delete.php'

    },

    reader: {

    type: 'json',

    root: 'data',

    successProperty: 'success'

    },

    writer: {

    type: 'json',

    writeAllFields: true,

    encode: false,

    root: 'data'

    }

    }

     
    }); 
    我们想在工具栏中添加“新增”和“删除按钮”,代码如下:

    var rowEditor = Ext.create('Ext.grid.plugin.RowEditing', {

    clicksToEdit: 1

     
    })
     

    var grid = Ext.create('Ext.grid.Panel', {

    //other config options

    plugins: rowEditor,

    dockedItems: [{

    xtype: 'toolbar',

    items: [{

    text: 'Add',

    handler : function() {

    rowEditor.cancelEdit();

    // Create a record instance through the ModelManager

    var r = Ext.ModelManager.create({

    name: 'New Contact',

    email: 'newcontact@email.com',

    phone: '1111-1111'

    }, 'Contact');

    Contacts.insert(0, r);

    rowEditor.startEdit(0, 0);

    }

    },{ 

    text: 'Delete',

    handler: function() {

    var sm = grid.getSelectionModel();

    rowEditor.cancelEdit();

    Contacts.remove(sm.getSelection());

    if (Contacts.getCount() > 0) {

         sm.select(0);

    }

    }

    }]

    }]

     
    }); 
    此时我们对Grid的任何修改将暂时保存在客户端的Store中,要保存到服务端就要调用Contacts.sync()了。
    若打算每次操作后马上将操作结果保存到服务端,就要为Contacts配置autoSync属性为true了。
     
    5.1.3.4. 无限滚动                                                  
         (译者语:因没有在API文档中找到对应的配置项说明,并实践中也没有成功过,所以不打算翻译该节内容,若大家成功实现该功能,请告之,谢谢)
     
    5.2. Tree                                                      
         和Grid一样Tree在Extjs4中被大大地简化了。Tree和Grid一样是Ext.panel.Table的子类,也就是说Grid中大部分能使用的功能,同样能在Tree中使用。
    我们先回顾一下如何在Extjs3中创建一棵简单的Tree吧

    new Ext.tree.TreePanel({

    renderTo: 'tree-example',

    title: 'Simple Tree',

    200,

    rootVisible: false,

    root: new Ext.tree.AsyncTreeNode({

    expanded: true,

    children: [

    { text: "Menu Option 1", leaf: true },

    { text: "Menu Option 2", expanded: true,

    children: [

    { text: "Sub Menu Option 2.1", leaf: true },

    { text: "Sub Menu Option 2.2", leaf: true}

    ] },

    { text: "Menu Option 3", leaf: true }

    ]

    })

     
    }); 
    而在Extjs4中,我们按如下方式创建一棵简单树

    Ext.create('Ext.tree.Panel', {

    title: 'Simple Tree',

    200,

    store: Ext.create('Ext.data.TreeStore', {

    root: {

    expanded: true,

    children: [

    { text: "Menu Option 1", leaf: true },

    { text: "Menu Option 2", expanded: true,

    children: [

    { text: "Sub Menu Option 2.1", leaf: true },

    { text: "Sub Menu Option 2.2", leaf: true}

    ] },

     
    { text: "Menu Option 3", leaf: true }

    ]

    }

    }),

    rootVisible: false,

    renderTo: 'tree-example'

     
    }); 
    两者效果图一样的:
    在Extjs4中我们可以看到三个与Tree相关的类:
    1. NodeInterface:对Node API的封装,表示每一个数节点(译者语:使用上与Model差不多);
    2. Tree:维护各个NodeInterface实例的关系;
    3. TreeStore:Store的子类,专门用于配置Tree的数据源。
     
    5.2.1. Drag-and-drop and sorting                                  
         拖拽在重新排列树节点位置时十分有用。通过下面的代码我们可以实现拖拽特性:

    Ext.create('Ext.tree.Panel', {

    store: store,

    viewConfig: {

    plugins: {

    ptype: 'treeviewdragdrop'

         }

    },

    //other properties

     
    }); 

    var store = Ext.create('Ext.data.TreeStore', {

    proxy: {

    type: 'ajax',

    api: {

    read : '../data/drag-drop.json',

    create : 'create.php'

    }

    },

    writer: {

    type: 'json',

    writeAllFields: true,

    encode: false

    },

    autoSync:true

     
    }); 
     
    而实现树节点排序代码如下:

    Ext.create('Ext.data.TreeStore', {

    folderSort: true,

    sorters: [{

    property: 'text',

    direction: 'ASC'

    }]

     
    });
    (译者语:本人觉得树节点排序的功能不大实用)
     
    5.2.2. Check Tree                                        
    要实现可复选的树是一件十分简单的事情,不信请看下列实例吧:
    这是树节点的数据

    [{

    "text": "Cartesian",

    "cls": "folder",

    "expanded": true,

    "children": [{

    "text": "Bar",

    "leaf": true,

    "checked": true

    },{

    "text": "Column",

    "leaf": true,

    "checked": true

    },{

    "text": "Line",

    "leaf": true,

    "checked": false

    }]

    },{

    "text": "Gauge",

    "leaf": true,

    "checked": false

    },{

    "text": "Pie",

         "leaf": true, 

    "checked": true

     
    }] 
     
    操作代码如下:

    var store = Ext.create('Ext.data.TreeStore', {

    proxy: {

    type: 'ajax',

    url: 'data/check-nodes.json'

    },

    sorters: [{

     
    property: 'leaf',

    direction: 'ASC'

    }, {

    property: 'text',

    direction: 'ASC'

    }]

    });

    Ext.create('Ext.tree.Panel', {

    store: store,

    rootVisible: false,

    useArrows: true,

    frame: true,

    title: 'Charts I have studied',

    renderTo: 'tree-example',

    200,

    height: 250

     
    });
    效果如下:
     
     
    5.2.3. Tree Grid                                            
         在Extjs3中Tree Grid作为额外组件的形式被使用。而在Extjs4中它已变成原生API了。下面我们通过实例来学习吧!

    Ext.define('Book', {

     
    extend: 'Ext.data.Model',

    fields: [

    {name: 'book', type: 'string'},

    {name: 'pages', type: 'string'}

    ]

    });

    var store = Ext.create('Ext.data.TreeStore', {

    model: 'Book',

    proxy: {

    type: 'ajax',

    url: 'data/treegrid.json'

    },

    folderSort: true

     
    }); 
    到此我们已经定义数据源了,下面我们看Tree Grid组件的使用

    Ext.create('Ext.tree.Panel', {

    title: 'Books',

    500,

    height: 300,

    renderTo: Ext.getBody(),

    collapsible: true,

    useArrows: true,

    rootVisible: false,

    store: store,

    multiSelect: true,

    singleExpand: true,

    columns: [{

    xtype: 'treecolumn',

    text: 'Task',

    flex: 2,

    sortable: true,

    dataIndex: 'task'

    },{

    text: 'Assigned To',

    flex: 1,

    dataIndex: 'user',

    sortable: true

    }]

     
    });
    上面的代码中高亮部分columns属性和Ext.grid.Panel的columns属性是一样的。而要注意的是第一列的列类型为treecolumn,那么这列就是可展开的树节点列了。
     
    效果如下:
     
    5.3. Form                                            
         Ext.form.Panel提供一个form的容器。我们通常使用form来管理数据。在Extjs4中form由Fields、FieldContainer、FieldSet、Label和Actions组成。下面我们先通过实例在学习Fields。
       
    5.3.1. Form fields                                              
         Extjs4引入了Ext.form.field包,所有的Form field都属于该包。我们通过实例来看各个field的效果吧

    Ext.create('Ext.form.Panel', {

    frame: true,

    title: 'Form Fields',

    340,

    bodyPadding: 5,

    renderTo: 'form-example',

    fieldDefaults: {

    labelAlign: 'left',

    labelWidth: 90,

    anchor: '100%'

    },

    items: [{

    xtype: 'hiddenfield', //1

    name: 'hiddenfield1',

    value: 'Hidden field value'

    },{

    xtype: 'displayfield', //2

    name: 'displayfield1',

    fieldLabel: 'Display field',

    value: 'Display field <span style="color:red;">value</span>'

    },{

    xtype: 'textfield', //3

    name: 'textfield1',

    fieldLabel: 'Text field',

    value: 'Text field value'

    },{

    xtype: 'textfield', //4

    name: 'password1',

    inputType: 'password',

    fieldLabel: 'Password field'

    },{

    xtype: 'textareafield', //5

    name: 'textarea1',

    fieldLabel: 'TextArea',

    value: 'Textarea value'

    },{

     
    xtype: 'filefield', // 6

    name: 'file1',

    fieldLabel: 'File upload'

    },{

    xtype: 'timefield', //7

    name: 'time1',

    fieldLabel: 'Time Field',

    minValue: '8:00 AM',

    maxValue: '5:00 PM',

    increment: 30

    },{

    xtype: 'datefield', //8

    name: 'date1',

    fieldLabel: 'Date Field',

    value: new Date()

    },{

    xtype: 'combobox', //9

    fieldLabel: 'Combobox',

    displayField: 'name',

    store: Ext.create('Ext.data.Store', {

    fields: [

    {type: 'string', name: 'name'}

    ],

    data: [

    {"name":"Alabama"},

    {"name":"Alaska"},

    {"name":"Arizona"},

    {"name":"Arkansas"},

    {"name":"California"}

    ]

    }),

    queryMode: 'local',

    typeAhead: true

    },{

    xtype: 'numberfield',

    name: 'numberfield1', //10

    fieldLabel: 'Number field',

    value: 20,

    minValue: 0,

    maxValue: 50

    },{

    xtype: 'checkboxfield', //11

    name: 'checkbox1',

    fieldLabel: 'Checkbox',

     
    boxLabel: 'box label'

    },{

    xtype: 'radiofield', //12

    name: 'radio1',

    value: 'radiovalue1',

    fieldLabel: 'Radio buttons',

    boxLabel: 'radio 1'

    },{

    xtype: 'radiofield', //13

    name: 'radio1',

    value: 'radiovalue2',

    fieldLabel: '',

    labelSeparator: '',

    hideEmptyLabel: false,

    boxLabel: 'radio 2'

    },{

    xtype: 'multislider', //14

    fieldLabel: 'Multi Slider',

    values: [25, 50, 75],

    increment: 5,

    minValue: 0,

    maxValue: 100

    },{

    xtype: 'sliderfield', //15

    fieldLabel: 'Single Slider',

    value: 50,

    increment: 10,

    minValue: 0,

    maxValue: 100

    }]

     
    }); 
    上述代码片段中,我们设置了fieldDefaults属性。该属性会应用到所有label实例的field中(即继承Ext.form.field.Base或Ext.form.FieldContainer的类)。这里我们设置了所有field的labelWidth为90px,而field将占用容器100%的宽度。
    效果图如下:
    下面我们来学习各种field吧!
    1. hidden field(xtype:"hiddenfield"):用于保存不向用户显示但需要保存并发送到服务端的内容。例如Id,我们并不想将Id值向用户显示,但在执行更新等操作时我们需要将Id值发送到服务端;
    2. display field(xtype:"displayfield"):用于显示只读内容;
    3. text field(xtype:"textfield"):用于输入简单文本内容;若inputType设置为password就会变成密码输入框;
    4. textarea(xtype:"textareafield"):用于输入多行简单文本内容,是textfield的子类;
    5. field upload field(xtype:"filefield"):用于文件上传;
         以下为继承Trigger类的field,其中共有Picker类型和Spinner类型的field。Picker类型的field会有一个按钮,当点击按钮时就会弹出一个供选择值的弹窗。而Spinner类型的field会有个滑动块来选择值。
    6. time field(xtype:"timefield"):通过配置minValue和maxValue属性来限定最小和最大的时刻。如上述例子中分别设置最小时刻为8:00 AM和最大时刻5:00 PM。并且我们可以通过increment设置时刻间隔(例子中设置为30分钟);
    7. date field(xtype:"datefield"):用于设置日期。实例中设置默认值为当前日期;
    8. combox field(xtype:"combobox"或xtype:"combo"):下拉列表,需要使用Store做为数据源;
    9. number field(xtype:"numberfield"):用于输入纯数字值;若不想显示向上向下按钮的话就要设置以下的属性
         hideTrigger:true,
         keyNavEnabled: false,
         mouseWheelEnabled: false
    10. checkbox(xtype:"checkboxfield"或xtype:"checkbox");
    11. radio field(xtype:"radiofield"或xtype:"radio"):checkbox的子类;
    12. multi-slider field(xtype:"multislider"):用于在某个数值范围内选择多个值;
    13. single slider field(xtype:"slider"或xtype:"sliderfield"):用于在某个数值范围内选择单个值。
     
    5.3.2. Validation                                              
         对用户输入的不信任我想是一种软件开发的法则了,那么对用户输入的验证是必不可少的。下面我们就学习以下吧!

    Ext.create('Ext.form.Panel', {

    frame: true,

    title: 'Form Fields Validation',

    340,

    bodyPadding: 5,

    renderTo: 'form-example',

    fieldDefaults: {

    labelAlign: 'left',

    labelWidth: 90,

    anchor: '100%',

    msgTarget: 'under'

    },

    items: [{

    xtype: 'textfield',

    name: 'textfield1',

    fieldLabel: 'Required',

    allowBlank: false //1

    },{

    xtype: 'textfield',

    name: 'textfield2',

    fieldLabel: 'Min 2',

    minLength: 2 //2

    },{

    xtype: 'textfield',

    name: 'textfield3',

    fieldLabel: 'Max 5',

    maxLength: 5 //3

     
    },{

    xtype: 'textfield',

    name: 'textfield7',

    fieldLabel: 'Regex - Phone',

    regex: /^d{3}-d{3}-d{4}$/, //4

    regexText: 'Must be in the format xxx-xxx-xxxx'

    },{

    xtype: 'textfield',

    name: 'textfield4',

    fieldLabel: 'Email',

    vtype: 'email' //5

    },{

    xtype: 'textfield',

    name: 'textfield5',

    fieldLabel: 'Alpha',

    vtype: 'alpha' //6

    },{

    xtype: 'textfield',

    name: 'textfield6',

    fieldLabel: 'AlphaNum',

    vtype: 'alphanum' //7

    },{

    xtype: 'textfield',

    name: 'textfield6',

    fieldLabel: 'Url',

    vtype: 'url' //8

    },{

    xtype: 'textfield',

    name: 'textfield8',

    fieldLabel: 'Custom: IP Address',

    vtype: 'IPAddress' //9

    }]

     
    }); 
    当我们验证某个输入为不合法时就需要将错误信息反馈给用户,而msgTarget就是可以配置错误信息是在field的side、under还是top显示。
    验证的类型有:
    1. allowBlank:设置是否允许输入空内容;
    2. maxLength:设置输入内容的最长字数;
    3. minLength:设置输入内容的最短字数;
    4. regex:设置正在表达式来验证输入内容;
    5. vtype:内置的验证规则(alpha,alphanum,email,url),用于限制输入和验证输入内容。当然我们可以自定义验证规则

    Ext.apply(Ext.form.field.VTypes, {

         IPAddress: function(v) {

         return /^d{1,3}.d{1,3}.d{1,3}.d{1,3}$/.test(v););

         },

         IPAddressText: 'Must be a numeric IP address',

         IPAddressMask: /[d.]/i

         });
    这样我们就可以vtype:"IPAddress"来用该验证规则来限制输入和验证输入内容了。
     
    5.3.3. Form label                                       
         label是在form中呈现简单文本内容的组件。代码如下:

    Ext.create('Ext.form.Panel', {

    title: 'Form with Label',

    100,

    bodyPadding: 10,

    renderTo: 'form-example',

    items: [{

    xtype: 'label',

    forId: 'myFieldId',

    text: 'Just a Label',

    margins: '0 0 0 10'

    }]

     
    }); 
     
    5.3.4. Actions(操作)                                          
         对于form我们一般执行加载数据和提交数据两类操作。下面我们通过实例来学习:

    Ext.create('Ext.form.Panel', {

    title: 'Book Info',

    renderTo: 'form-example',

    300,

    bodyPadding: 5,

    fieldDefaults: {

    labelAlign: 'left',

    labelWidth: 90,

    anchor: '100%'

    },

    items: [{

    xtype: 'hiddenfield',

    name: 'bookId'},{

    xtype: 'textfield',

    name: 'bookName',

    fieldLabel: 'Title'

    },{

    xtype: 'textfield',

    name: 'bookAuthor',

    fieldLabel: 'Author'

    }],

    buttons: [{

    text: 'Load',

    handler: function() {

    var form = this.up('form').getForm();

    form.load({

    url: 'data/form.json',

    failure: function(form, action) {

    Ext.Msg.alert("Load failed", action.result. errorMessage);

    }

    });

    }

    },{

    text: 'Submit',

    handler: function() {

    var form = this.up('form').getForm();

    form.submit({

    url: 'form-submit.php',

    waitMsg: 'Sending the info...',

    success: function(fp, o) {

    Ext.Msg.alert('Success', 'Form submitted.');

    }

    });

    }

    }]

     
    }); 
         这里我们通过this.up("form").getForm()的方式得到Ext.form.Basic类,然后才能对表单进行数据合法性验证、加载数据和提交数据等操作。
         加载数据时我们需要调用load操作,具体设置请参考API文档中的Ext.form.action包下的类。
    加载数据的格式如下:

    {

    success: true,

    data: {

    bookId: 10,

    bookName: "Ext JS 4 First Look",

    bookAuthor: "Loiane Groner"

    }

     
     
    5.4. 总结                                                    
         通过本章的学习,我想大家已经对Grid、Tree和Form的使用有一定的了解。当然这里只是简单的介绍它们,要想用得好还是要靠大家多实践的!
  • 相关阅读:
    引入包时“”与<>的区别
    Scanners
    一个SQLite数据库的LIKE查询和IN集合查询的代码实例
    @synchronized线程同步互斥锁
    makeKeyAndVisible
    NSString 数字判断
    UILabel UITextField UITextView
    (转载)JAVA SE6.0 中使用SplashScreen
    转帖(http://hi.baidu.com/johnehuang/blog/item/e1e96782a4b04e97f703a6dc.html)
    ce
  • 原文地址:https://www.cnblogs.com/niejunchan/p/4998512.html
Copyright © 2020-2023  润新知