ExtJS教程汇总: https://www.cnblogs.com/cqpanda/p/16328016.html
转载请注明出处: https://www.cnblogs.com/cqpanda/p/16587410.html

表单面板介绍

Ext.form.panel面板继承自Ext.panel.Panel 并 添加与表单相关的功能
比如:表单字段管理(Field management)、验证(Validation)、提交(Submission)等,使用Ajax提交和加载数据。
注意:File提交效果看似Ajax,但实际并非Ajax,而是在新的 <iframe> 进行上传数据

表单面板布局

表单面板默认使用anchor布局,可以自己手动修改

表单面板可以使用其他布局或者组件,比如带Card布局的标签面板

表单面板数据

使用setValues方法为表单加载数据
使用getValues方法来获取表单数据
使用setRecord方法将模型实例的数据加载到表单
使用updateRecord更新表单记录
使用getRecord方法返回绑定的模型实例
使用submit方法提交表单
使用reset方法重置表单

表单面板(Ext.form.Panel)

实例:基本表单面板

xtype: 'form', title: 'Panda Form Title', //标题 width: 500, //宽度 height: 300, //高度 frame: true, //显示边框 draggable: true, //可拖拽 collapsible: true, //可折叠 closable: true, //可关闭 modal : true, //遮罩 center : true, //居中 dockedItems: [ //工具栏 items: [ //子项

实例:设置标签默认的宽度

使用labelWidth配置项即可

xtype: 'form', title: 'Panda Form Panel Title', width: 500, height: 300, labelWidth: 100, //设置标签的宽度 renderTo: document.body, items: [

实例:设置表单元素默认的类型

使用defaultType配置项即可

xtype: 'form', title: 'Panda Form Panel Title', width: 500, height: 300, defaultType: 'textfield', //设置默认的表单元素类型 defaults: { //设置表单元素默认的配置 msgTarget: 'under', //提示消息显示位置 anchor: '-10' //默认位置修改 renderTo: document.body, items: [

实例:设置表单元素默认的配置

使用defaults配置项即可

xtype: 'form', title: 'PandaFormPanelTitle', width: 350, height: 500, defaults: { //设置表单元素默认的配置 msgTarget: 'under', //提示消息显示位置 anchor: '-10' //默认位置修改 renderTo: document.body, items: [

实例:获得表单的指定组件

let firstNameField = formPanel.items.get(0).items.get(0);

实例:用对象填充表单组件的值

formPanel.getForm().setValues(requestData);

实例:用model填充表单组件的值

//定义一个Model用于填充使用
Ext.define('Request', {
    extend: 'Ext.data.Model',
    fields: [
        'FirstName',
        'LastName',
        'EmailAddress',
        'TelNumberCode',
        'TelNumber',
        'RequestDetails',
        'RequestType'
//用对象去填充Model
//实际使用中,从后端加载Model的数据
var requestModel = Ext.create('Request', requestData);
//使用Model初始化Form
formPanel.getForm().setRecord(requestModel);

实例:从服务器加载表单的值

formPanel.getForm().load({
    url: 'requestDetails.json'

注意:返回的json要带success参数

返回JSON格式实例:

"success": true, "data": {

实例:文件上传等待提示

//获得表单组件
let form = this.up('form').getForm();
//验证表单内容是否有效
if (form.isValid()) {
    //提交表单
    form.submit({
        url: 'upload.php',
        //显示的等待提示文本信息
        waitMsg: 'Uploading...'

实例:POST方式提交表单

formPanel.getForm().submit({
        url: 'submit.php'

实例:提交表单(Ajax方式)

xtype: 'form', title: 'Panda Form', minWidth: 400, minHeight: 300, maxWidth: 800, maxHeight: 500, width: 450, height: 300, draggable: true, closable: true, labelWidth: 100, //设置标签的宽度 layout: 'column', bodyPadding: 50, items: [ xtype: 'textfield', fieldLabel: '用户名', name: 'username', columnWidth: 1, minLength: 5, maxLength: 16, msgTarget: 'under', allowBlank: false xtype: 'textfield', fieldLabel: '密码', inputType: 'password', name: 'password', margin: '10 0 0 0', columnWidth: 1, minLength: 5, maxLength: 16, msgTarget: 'under', allowBlank: false xtype: 'fieldcontainer', columnWidth: 1, layout: 'hbox', margin: '30 0 0 0', items: [ xtype: 'button', text: '确认提交', flex: 1, handler: function(){ //获得表单 var form = this.up('form').getForm(); //验证是否满足基本验证 if(form.isValid()) console.log('验证通过'); //获得表单的所有域值 console.log(form.getValues()); //提交数据 form.submit({ url:'/submitaction.php', //提交的URL //成功回调 success: function(form, action){ Ext.Msg.alert('Success', 'Successfully saved'); //错误回调 failure: function(form, action){ if (action.failureType === Ext.form.action.Action.CLIENT_INVALID) Ext.Msg.alert('CLIENT_INVALID ', 'Something has been missed. Please check and try again.'); if (action.failureType === Ext.form.action.Action.CONNECT_FAILURE) Ext.Msg.alert('CONNECT_FAILURE', 'Status: ' + action.response.status + ': ' + action.response.statusText); if (action.failureType === Ext.form.action.Action.SERVER_INVALID) Ext.Msg.alert('SERVER_INVALID', action.result.message); console.log('验证失败'); xtype: 'button', text: '重新填写', flex: 1, margin: '0 0 0 10', handler: function(){ //获得表单 var username = this.up('form').down('textfield[name="username"]'); var password = this.up('form').down('textfield[name="password"]'); username.setValue(''); password.setValue('');

实例:提交表单(Ajax方式)

服务器端Ajax格式:
成功格式:

success: true, msg: 'This is Success Data'

失败格式:

success: false, msg: 'This is Error Data', errors: { firstName: '不可以为空', lastName: '不可以为特殊字符'
//获得表单
var form = this.up('form').getForm();
//验证是否满足基本验证
if(form.isValid())
    console.log('验证通过');
    console.log(form.getValues());
    //提交数据
    form.submit({
        url: '/test.json',
        method: 'get', //或者post
        success: function(form, action){
            //验证服务器端是否发回成功信息
            if(action.result.success)
                //输出成功信息
                console.log(action.result.msg);
        failure: function(form, action){
            //服务器端验证失败
            console.log(action.result.msg);
            //输出错误信息
            console.log(action.result.errors);
    console.log('客户端本地验证失败');

实例:提交表单(传统方式)

使用发送HTTP 表单的方式传送数据,将standardSubmit配置项设置为true即可。其他和ajax操作是一样的。

实例:把数据加载到表单中(服务器端数据)

用form组件的load方法即可。

服务器端数据格式:

success: true, data: { userName: 'Panda666', age: 18 var formPanel = Ext.create('Ext.form.Panel', { title: 'PandaFormPanelTitle', width: 350, height: 300, labelWidth: 100, //设置标签的宽度 renderTo: document.body, items: [ xtype: 'textfield', fieldLabel: '用户名', name: 'userName', minLength: 5, maxLength: 16, msgTarget: 'under', allowBlank: false xtype: 'textfield', fieldLabel: '年龄', name: 'age', buttons: [ xtype: 'button', text: '确认提交' //填充数据 Ext.defer(function(){ formPanel.getForm().load({ url: '/test.json', method: 'get', success: function(){ console.log('Add Data Success'); }, 2000);

实例:把数据加载到表单中(本地数据)

var formPanel = Ext.create('Ext.form.Panel', { title: 'PandaFormPanelTitle', width: 350, height: 300, labelWidth: 100, //设置标签的宽度 renderTo: document.body, items: [ xtype: 'textfield', fieldLabel: '用户名', name: 'userName', minLength: 5, maxLength: 16, msgTarget: 'under', allowBlank: false xtype: 'textfield', fieldLabel: '年龄', name: 'age', buttons: [ xtype: 'button', text: '确认提交' //填充数据 Ext.defer(function(){ //data var data = { userName: 'Panda666', age: 18 //填充数据 formPanel.getForm().setValues(data); }, 2000);

实例:表单事件处理

beforeaction: 在执行任何操作之前将触发此事件
actionfailed: 当操作失败时将触发此事件
actioncomplete: 此事件将在操作完成后激发
validitychange: 当整个表单的有效性更改时,将触发此事件
dirtychange: 当窗体的脏状态更改时,将触发此事件

实例:显示表单

var formPanel = Ext.create('Ext.form.FormPanel', {
    width: 300,
    itemId : 'formPanel',
    frame : true,
    renderTo: Ext.getBody(),
    layout : 'anchor',
    defaultType : 'textfield',
    defaults : {
        anchor : '-10',
        labelWidth : 65
    items : [
            fieldLabel : 'First name',
            name : 'firstName'
            fieldLabel : 'Last name',
            name : 'lastName' 
    buttons : [
            text : 'Submit',
            handler : function() {
                var formPanel = this.up('#formPanel');
                var values = formPanel.getValues();
                console.log('firstName = ' + values.firstName);
                console.log('lastName = ' + values.lastName);
            text : "Reset",
            handler : function() {
                var formPanel = this.up('#formPanel');
                formPanel.form.reset();

实例:简单表单

Ext.create('Ext.form.Panel', {
    id: 'newForm',
    renderTo: Ext.getBody(),
    border: true,
    width: 600,
    items: [{
        xtype: 'textfield',
        fieldLabel: 'Text Field'
        xtype: 'displayfield',
        fieldLabel: 'Display Field'
        xtype: 'textarea',
        fieldLabel: 'Text Area'
        xtype: 'datefield',
        fieldLabel: 'Date picker'
        xtype: 'button',
        text: 'Button'
        xtype: 'fieldcontainer',
        fieldLabel: 'Radio field',
        defaultType: 'radiofield',
        defaults: {
            flex: 1
        layout: 'hbox',
        items: [{
            boxLabel: 'A',
            inputValue: 'a',
            id: 'radio1'
            boxLabel: 'B',
            inputValue: 'b',
            id: 'radio2'
            boxLabel: 'C',
            inputValue: 'c',
            id: 'radio3'
        xtype: 'fieldcontainer',
        fieldLabel: 'Check Box Field',
        defaultType: 'checkboxfield',
        items: [{
            boxLabel: 'HTML',
            inputValue: 'html',
            id: 'checkbox1'
            boxLabel: 'CSS',
            inputValue: 'css',
            checked: true,
            id: 'checkbox2'
            boxLabel: 'JavaScript',
            inputValue: 'js',
            id: 'checkbox3'
        xtype: 'hiddenfield',
        name: 'hidden field ',
        value: 'value from hidden field'
        xtype: 'numberfield',
        anchor: '100%',
        fieldLabel: 'Numeric Field',
        maxValue: 99,
        minValue: 0
        xtype: 'spinnerfield',
        fieldLabel: 'Spinner Field',
        step: 6,
        // override onSpinUp (using step isn't necessary)
        onSpinUp: function() {
            var me = this;
            if (!me.readOnly) {
            var val = me.step;    // set the default value to the step value
            if(me.getValue() !== '') {
                val = parseInt(me.getValue().slice(0, -5));   // gets rid of " Pack"
            me.setValue((val + me.step) + ' Pack');
        // override onSpinDown
        onSpinDown: function() {
            var me = this;
            if (!me.readOnly) {
            if(me.getValue() !== '') {
                val = parseInt(me.getValue().slice(0, -5));   // gets rid of " Pack"
            me.setValue((val - me.step) + ' Pack');
        xtype: 'timefield',
        fieldLabel: 'Time field',
        minValue: '6:00 AM',
        maxValue: '8:00 PM',
        increment: 30,
        anchor: '100%'
        xtype: 'combobox',
        fieldLabel: 'Combo Box',
        store: Ext.create('Ext.data.Store', {
            fields: ['abbr', 'name'],
            data: [{
            'abbr': 'HTML',
            'name': 'HTML'
            'abbr': 'CSS',
            'name': 'CSS'
            'abbr': 'JS',
            'name': 'JavaScript'
        valueField: 'abbr',
        displayField: 'name'
        xtype: 'filefield',
        fieldLabel: 'File field',
        labelWidth: 50,
        msgTarget: 'side',
        allowBlank: false,
        anchor: '100%',
        buttonText: '选择文件...'

实例:绑定字段的数据到ViewModel

在视图中使用bind配置项

xtype : 'textarea', fieldLabel: 'Description', height : 100, bind : '{rec.Description}' xtype : 'numberfield', fieldLabel: 'Quantity', bind : '{rec.Quantity}'

在ViewController中引用ViewModel,并绑定数据

productForm.getViewModel().setData({
    rec: rec

实例:保存、取消、关闭表单

onSave: function(btn){
    var productModel = this.getView().getViewModel().getData().rec;
    productModel.commit();
    this.closeForm();
onCancel: function(btn){
    var productModel = this.getView().getViewModel().getData().rec;
    productModel.reject();
    this.closeForm();
closeForm: function(){
    varproductForm=this.getView();
    productForm.close();
    productForm.destroy();

实例:简单表单实例

var formPanel = Ext.create('Ext.form.Panel', {
    title: 'PandaFormPanelTitle', //标题
    width: 350,        //宽度
    height: 500,       //高度
    frame: true,       //显示边框
    draggable: true,   //可拖拽
    collapsible: true, //可折叠
    closable: true,    //可关闭
    modal : true,      //遮罩
    center : true,     //居中
    renderTo: document.body,
    dockedItems: [ //工具栏
            xtype: 'toolbar',
            dock: 'bottom',
            items: [
                    xtype: 'tbfill'
                    xtype: 'button',
                    text: '保存'
            xtype: 'toolbar',
            dock: 'top',
            items: [
                    xtype: 'button',
                    text: '新增'
                    xtype: 'button',
                    text: '编辑'
                    xtype: 'tbfill'  //空格
                    xtype: 'button',
                    text: '<b>删除</b>'
    defaults: {
        anchor: '100%',
        xtype: 'textfield',
        padding: '5 15 5 15',
    items: [   //子项
            xtype: 'numberfield',
            fieldLabel: '客户Id'
            fieldLabel: '客户姓名'
            fieldLabel: '客户电话'
            xtype: 'datefield',
            fieldLabel: '客户加入日期'
            xtype: 'combobox',
            fieldLabel: '客户状态'

字段集(fieldset)

构建复杂的表单,需要多个字段集(fieldset)
字段类型一般继承自Ext.form.field.Base类型
该类还mixins了Ext.form.Labelable类型和 Ext.form.field.Field类型

Ext.form.Labelable类用于字段类型可以显示标签,比如textfields, comboboxes等

实例:简单的字段集

xtype:'fieldset', width: 700, title: 'User Information', renderTo: document.body, border: true, flex: 1, items: [ xtype: 'textfield', fieldLabel: 'UserName', name: 'userName', xtype: 'textfield', fieldLabel: 'Age', name: 'age', value: 18

实例:可折叠字段集

使用collapsible配置项即可。

xtype: 'fieldset', title: '字段集', collapsible: true, //开启可折叠 items: [ xtype: 'textfield', fieldLabel: 'Username'

ExtJS内建表单字段

所在的命名空间是:

Ext.form.field      //classic包
Ext.field           //modern包
以下是常用的表单字段:
Ext.form.field.Text         //文本域
Ext.form.field.Radio        //单选
Ext.form.field.Checkbox     //多选框
Ext.form.field.ComboBox     //列表框
Ext.form.field.Date         //日期选择
Ext.form.field.Time         //时间选择
Ext.form.field.File         //文件上传
Ext.form.field.Hidden       //隐藏域
Ext.form.field.HtmlEditor   //富文本编辑器
Ext.form.field.Number       //数值选择
Ext.form.field.TextArea     //文本框
显示文本(displayfield)
Ext.form.Label

字符显示框

实例:简单的文本

xtype: 'displayfield', fieldLabel: 'Display Field',

文本框(textfield)

实例:简单文本框

xtype: 'textfield', fieldLabel: 'Text field',

实例:简单文本框

使用margin设置外边距
使用fieldLabel设置文本域的提示字符(Label标签)
使用name设置表单的name属性

xtype: 'textfield', //文本框 fieldLabel: 'UserName', //label name: 'UserName', //html name属性 margin: '10,0,0,0', //设置外边距

实例:设置标签文本的宽度

xtype: 'textfield', //文本框 labelWidth: 70, //设置标签的宽度 fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置

实例:设置文本自动伸缩

使用grow配置项即可。

xtype: 'textfield', //文本框 labelWidth: 70, //设置标签的宽度 fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 grow: true, //设置输入框自动伸缩

实例:选中自动聚焦所有文本

使用selectOnFocus配置项。

xtype: 'textfield', //文本框 labelWidth: 70, //设置标签的宽度 fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 selectOnFocus: true, //选中的时候,自动选中全部文本

实例:设置标签文本的对齐位置

使用labelAlign设置对齐方式,支持值:top|bottom|left|right

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置

实例:验证自定义正则表达式

使用regex配置项、regexText配置项。

xtype: 'textfield', //文本框 labelWidth: 70, //设置标签的宽度 fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 regex: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^]{8,16}$/, regexText: '至少8-16个字符,至少1个大写字母,1个小写字母和1个数字,其他可以是任意字符。',

实例:验证邮箱(使用vtype)

使用vtype设置验证的类型
使用msgTarget属性设置显示消息的位置,支持值:side、under

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'Email', //label name: 'email', //html name属性 msgTarget: 'under', //消息显示位置 allowBlank: false, //是否可以为空 vtype: 'email'

实例:验证URL邮箱(使用vtype)

使用vtype设置验证的类型

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 allowBlank: false, //是否可以为空 vtype: 'url', //设置验证是否URL msgTarget: 'under', //显示消息在右侧

实例:验证必须是字母(使用vtype)

xtype: 'textfield', //文本框 labelWidth: 70, //设置标签的宽度 fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 vtype: 'alpha', //验证必须是字母

实例:验证必须是数值或字母(使用vtype)

xtype: 'textfield', //文本框 labelWidth: 70, //设置标签的宽度 fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 vtype: 'alphanum', //验证必须数值或字母

实例:验证网址(使用vtype)

该功能有BUG,无法验证https。请自定义验证。

xtype: 'textfield', //文本框 labelWidth: 70, //设置标签的宽度 fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 vtype: 'url', //验证必须是url

实例:验证自定义规则-验证必须是时间(使用vtype)

override Ext.form.field.VTypes类型即可。

// custom Vtype for vtype:'time'
Ext.define('Override.form.field.VTypes', {
    override: 'Ext.form.field.VTypes',
    // vtype validation function
    time: function(value) {
        return this.timeRe.test(value);
    //需要验证的正则表达式
    timeRe: /^([1-9]|1[0-9]):([0-5][0-9])(\s[a|p]m)$/i,
    //验证错误显示的文本
    timeText: '验证出现错误,请使用"12:34 PM"格式',
    //输入限制
    timeMask: /[\d\s:amp]/i
//使用自定义验证
Ext.create({
    xtype: 'textfield',   //文本框
    labelWidth: 70,       //设置标签的宽度
    fieldLabel: 'UserName', //label
    name: 'UserName',       //html name属性
    msgTarget: 'under',     //消息显示位置
    vtype: 'time',           //验证必须是时间
    renderTo: Ext.get('test'),

实例:验证自定义规则-验证必须是IP地址(使用vtype)

override Ext.form.field.VTypes类型即可。

//验证IP地址
Ext.define('Override.form.field.VTypes', {
    override: 'Ext.form.field.VTypes',
    //操作函数
    iPAddress:  function(value) {
        return this.iPAddressRe.test(value);
    //验证正则
    iPAddressRe: /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
    //提示文本
    iPAddressText: 'Must be a numeric IP address',
    //输入限制
    iPAddressMask: /[\d\.]/i
Ext.create({
    xtype: 'textfield',   //文本框
    labelWidth: 70,       //设置标签的宽度
    fieldLabel: 'UserName', //label
    name: 'UserName',       //html name属性
    msgTarget: 'under',     //消息显示位置
    vtype: 'iPAddress',           //验证必须是IP地址
    renderTo: Ext.get('test'),

实例:密码框

xtype: 'textfield', //文本框 inputType: 'password', //设置为输入密码 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'password', //label name: 'password', //html name属性 msgTarget: 'under', //消息显示位置 allowBlank: false, //是否可以为空

实例:设置默认空白显示的文本

使用emptyText配置项设置空白显示的文本

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 allowBlank: false, //是否可以为空 emptyText: 'Please Input Your Name', //提示文本 msgTarget: 'under', //显示消息在右侧 margin: '10,0,0,0', //设置外边距

实例:设置是否允许为空

使用allowBlank配置项设置文本域是否可以为空

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 allowBlank: true, //是否可以为空 emptyText: 'Please Input Your Name', //提示文本 msgTarget: 'under', //显示消息在右侧 margin: '10,0,0,0', //设置外边距

实例:设置字符长度(最长最短限制)

使用maxLength设置最大长度
使用maxLengthText设置错误提示文本
使用minLength设置最小长度
使用minLengthText设置错误提示文本

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 allowBlank: true, //是否可以为空 emptyText: 'Please Input Your Name', //提示文本 msgTarget: 'under', //显示消息在右侧 margin: '10,0,0,0', //设置外边距 maxLength: 10, //最大长度 maxLengthText: '用户名最多{0}个字符', //提示文本 minLength: 2, //最小长度 minLengthText: '用户名最少{0}个字符', //提示文本

实例:验证只允许输入的字符(大小写字母)

使用maskRe设置允许输入的字符,需要使用正则表达式

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 allowBlank: true, //是否可以为空 emptyText: 'Please Input Your Name', //提示文本 msgTarget: 'under', //显示消息在右侧 margin: '10,0,0,0', //设置外边距 maskRe: /[a-z]/i, //设置允许输入的字符

实例:验证只允许输入的字符(数值)

使用maskRe设置允许输入的字符,需要使用正则表达式

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 allowBlank: true, //是否可以为空 emptyText: 'Please Input Your Name', //提示文本 msgTarget: 'under', //显示消息在右侧 margin: '10,0,0,0', //设置外边距 maskRe: /[0-9]/i, //设置允许输入的字符

实例:验证只允许输入的字符(标点符号)

使用maskRe设置允许输入的字符,需要使用正则表达式

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //消息显示位置 allowBlank: true, //是否可以为空 emptyText: 'Please Input Your Name', //提示文本 msgTarget: 'under', //显示消息在右侧 margin: '10,0,0,0', //设置外边距 maskRe: /[,|.|/|~|,]/i, //设置允许输入的字符

实例:过滤输入的字符

使用stripCharsRe配置项设置过滤输入的字符

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //显示消息在右侧 stripCharsRe: /[a-z]/i, //过滤不需要的字符

实例:监听键盘事件

需要先开启键盘事件enableKeyEvents : true
然后再监听键盘对应的事件即可

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //显示消息在右侧 enableKeyEvents : true, //开启键盘事件 listeners: { keyup:{ //监听按钮弹起事件 fn:function( thisField, evt, eOpts ){ //监听回车键 if(evt.getCharCode() === evt.ENTER){ if (thisField.getValue()!=''){ Ext.Msg.alert('Alert','Welcome: '+ thisField.getValue() );

实例:设置触发器

触发器就是在文本框内部的按钮,点击后触发各种操作

xtype: 'textfield', //文本框 labelWidth: 170, //设置标签的宽度 labelAlign:'top', //对齐方式,top|bottom|left|right fieldLabel: 'UserName', //label name: 'UserName', //html name属性 msgTarget: 'under', //显示消息在右侧 triggers: { //触发器 searchtext: { //搜索按钮事件 cls: 'x-form-search-trigger', handler: function() { Ext.Msg.alert('Alert', '查找的内容是: ' + this.getValue()); cleartext: { //清除文本事件 cls: 'x-form-clear-trigger', handler: function() { Ext.Msg.alert('Alert', '已清除'); this.setValue('');

实例:设置表单验证错误信息显示的位置

使用msgTarget属性设置显示消息的位置
side 在输入框的右侧渲染一个惊叹号图标(没有文本提示)
under 把报错信息显示在输入框之下
title 在hover字段框时显示内容
qtip 触发mouseover事件会显示一个Ext JS小技巧
[elementid] 把报错信息的文本作为目标元素的innerHTML添加

注意:只有在formPanel内,表单元素的msgTarget才会支持所有值,默认为qtip

var formPanel = Ext.create('Ext.form.Panel', {
    title: 'PandaFormPanelTitle',
    width: 350,
    height: 500,
    renderTo: document.body,
    items: [
            xtype: 'textfield',
            fieldLabel: '用户名',
            name: 'UserName',
            minLength: 5,
            maxLength: 16,
            msgTarget: 'under',  //底部显示
            allowBlank: false
            xtype: 'textfield',
            fieldLabel: 'url',
            vtype: 'url',
            msgTarget: 'qtip',   //鼠标hover显示
            xtype: 'textfield',
            fieldLabel: '密码',
            name: 'password',
            msgTarget: 'under',  //底部显示
            allowBlank: false

滑块组件(Slider)

单滑块 Ext.slider.Single
多滑块 Ext.slider.Multi

实例:单滑块组件

Ext.create('Ext.slider.Single', {
    fieldLabel: 'Maximum Price',
    value: 100,
    minValue: 0,
    maxValue: 500,
    width: 400,
    increment: 10,

实例:多滑块组件

Ext.slider.Multi

Ext.create('Ext.slider.Multi', {
    fieldLabel: 'Price Range',
    minValue: 0,
    maxValue: 500,
    increment: 10,
    width: 400,

隐藏框(hiddenfield)

实例:简单隐藏框

xtype: 'hiddenfield',
value: 'value from hidden field'

多行文本框(textarea)

textArea类型扩展自textField类型

实例:简单文本框

xtype: 'textarea', fieldLabel: 'Text Area',

实例:设置文本框的高度

使用height配置项即可

xtype: 'textarea', fieldLabel: 'Text Area', height: 500, //设置高度

实例:设置文本框的宽度

使用width配置项即可

xtype: 'textarea', fieldLabel: 'Text Area', width: 1200 //设置宽度

实例:设置自动根据内容进行设置滚动条

使用scrollable配置项即可

xtype: 'textarea', fieldLabel: 'Text Area', scrollable: true //开启自动滚动

实例:设置样式

使用style配置项即可

xtype: 'textarea', fieldLabel: 'Text Area', style: { padding: 10

数值框(numberfield)

实例:基本数值框

xtype: 'numberfield', name: 'Count', //设置表单name属性 fieldLabel: 'Count', //显示的label标签文字

实例:设置初始值

使用value配置项设置初始值

xtype: 'numberfield', name: 'Count', //设置表单name属性 fieldLabel: 'Count', //显示的label标签文字 value: 10, //初始值

实例:设置上下限

使用maxValue配置项设置最大值
使用minValue配置项设置最小值

xtype: 'numberfield', name: 'Count', //设置表单name属性 fieldLabel: 'Count', //显示的label标签文字 value: 10, //初始值 maxValue: 10, //最大值 minValue: 0, //最小值

实例:设置是否允许小数

默认是允许小数点的
使用allowDecimals : false关闭小数点支持

xtype: 'numberfield', name: 'Count', //设置表单name属性 fieldLabel: 'Count', //显示的label标签文字 value: 10, //初始值 allowDecimals : false, //不支持小数

实例:设置小数精度

使用decimalPrecision配置项设置小数位精度

xtype: 'numberfield', name: 'Count', //设置表单name属性 fieldLabel: 'Count', //显示的label标签文字 value: 0.01, //初始值 decimalPrecision: 3 //设置精度

实例:设置步进值

使用step配置项设置步进值

xtype: 'numberfield', name: 'Count', //设置表单name属性 fieldLabel: 'Count', //显示的label标签文字 value: 1, //初始值 step: 2, //设置步进值

实例:开启鼠标滚轮支持

使用mouseWheelEnabled配置项开启鼠标滚轮支持
注意:默认是开启鼠标滚轮支持的

xtype: 'numberfield', name: 'Count', //设置表单name属性 fieldLabel: 'Count', //显示的label标签文字 value: 1, //初始值 step: 2, //设置步进值 mouseWheelEnabled: true //开启鼠标滚轮支持

实例:错误消息设置

xtype: 'numberfield', name: 'Count', //设置表单name属性 fieldLabel: 'Count', //显示的label标签文字 value: 1, //初始值 step: 2, //设置步进值 minValue: 2, //下限值 maxValue: 10, //上限值 negativeText : '{0} 不可为负数', //负数提示文本 nanText: '{0} 不是一个数字', //非数字提示文本 maxText: '超过了最大值,最大值为{0} ', //最大值提示文本 minText: '超过了最小值,最小值为{0} ', //最小值提示文本 msgTarget:'under', //错误消息显示位置

实例:隐藏右侧的上下拨动按钮

使用hideTrigger配置项即可

xtype: 'numberfield', name: 'Count', //设置表单name属性 fieldLabel: 'Count', //显示的label标签文字 value: 1, //初始值 step: 2, //设置步进值 hideTrigger:true //隐藏右侧的上下拨动按钮

实例:鼠标滚轮是否启用

//鼠标滚轮
mouseWheelEnabled:false

文件框(filefield)

实例:简单文件框

xtype: 'filefield', //文件框 fieldLabel: '请选择文件', name: 'pandaFile', width: 300, msgTarget: 'under', //错误消息显示位置classic errorTarget : 'under', //错误消息显示位置modern accept: 'image' //支持的文件类型

实例:设置按钮的文本

使用buttonText配置项即可

xtype: 'filefield', //文件框 buttonText: '请选择文件...', fieldLabel: '请选择文件', labelWidth: 70, name: 'pandaFile', width: 300, allowBlank: false, msgTarget: 'under', //错误消息显示位置classic errorTarget : 'under', //错误消息显示位置modern accept: 'image' //支持的文件类型

实例:设置支持上传的文件类型

使用accept配置项即可

xtype: 'filefield', //文件框 buttonText: '请选择文件...', fieldLabel: '请选择文件', labelWidth: 70, name: 'pandaFile', width: 300, allowBlank: false, msgTarget: 'under', //错误消息显示位置classic errorTarget : 'under', //错误消息显示位置modern accept: 'image' //支持的文件类型

组合框、列表框(ComboBox)

组合框就像多功能的文本输入框,既可以输入文本也可以选择文本
组件框框可以实现在文本输入区自动填充文本(也就是所谓的提前键入)
而且它可以连接远程数据存储,与服务器端配合过滤结果
针对大型数据集的远程请求,可以通过设置pageSize配置项来实现结果分页
注意:ComboBox一般需要与数据存储Store结合使用

实例:基本的ComboBox

xtype : 'combobox', fieldLabel: 'Combo box', queryMode: 'local', //本地查询模式 displayField: 'abbr', //要显示的Store字段 valueField: 'name', //传送到后端的Store字段 store: { //store数据来源 id : 'statesid', fields: ['abbr', 'name'], data : [ {"abbr":"HTML", "name":"HTML"}, {"abbr":"CSS", "name":"CSS"}, {"abbr":"JS", "name":"JavaScript"}

实例:自动填充

typeAhead: true,
typeAheadDelay: 100,  //提前查询延迟
minChars:最小字符数

实例:自定义显示内容

定义模板就行了

getInnerTpl: function(){
    return '<h3>{title} ({status})</h3>' +
    '<div class="reportedBy">Reported by {raisedBy}</div>' +
    '{body}';

实例:配置下拉列表设置

使用listConfig配置项即可。

xtype: 'combobox', listConfig: { emptyText: '没有数据', loadingText: '加载中...',

实例:设置默认选中值

使用value配置项即可

xtype: 'combo', fieldLabel: "选择姓名", //label标签的内容 displayField: 'name', //要显示的数据对应的Store字段 valueField: 'id', //值对应的Store字段 typeAhead: true, queryMode: 'local', //指定为本地数据存储查询 value: 12, //设置默认选中的值 store: { //指定数据来源 extend: 'Ext.data.Store', idProperty: 'id', fields: [ { name: 'id', type: 'int' }, { name: 'name', type: 'string' }, data: [ {id: 11, name: 'Panda666'}, {id: 12, name: 'dog666'}, {id: 13, name: 'cat666'}, {id: 14, name: 'Monkey666'}, {id: 15, name: 'Donkey666'},

实例:使用远程数据的组合框

测试使用的json数据

[{"id":666,"name":"Panda"},{"id":888,"name":"Dog"}]
//创建数据存储Store类型
Ext.define('PandaApp.store.UserComboBoxStore',{
    extend: 'Ext.data.Store',
    idProperty: 'id',
    fields: [
        { name: 'id', type: 'int' },
        { name: 'name', type: 'string' },
    autoLoad: true,
    proxy: {
        type: 'ajax',
        url : '/user.json',
        reader:{
            type: 'json',
//定义Store实例
var data = Ext.create('PandaApp.store.UserComboBoxStore');
//创建组合框
var combo = Ext.create({
    xtype: 'combo',
    fieldLabel: "选择姓名", //label标签的内容
    store: data,            //指定数据来源
    displayField: 'name',   //要显示的数据对应的Store字段
    valueField: 'id',       //值对应的Store字段
    typeAhead: true,
    queryMode: 'remote',     //指定为远程数据存储查询
    renderTo: document.body

实例:使用远程数据的组合框2

//data
var remoteData = Ext.create('Ext.data.JsonStore',{
    storeId: 'poeple',
    fields: [
        { name: 'id', type: 'int' },
        { name: 'fullName', type: 'string' }
    proxy: {
        type: 'jsonp',
        url: '/test.json',
        reader: {
            type: 'json',
            rootProperty: 'record',
            totalProperty: 'totalCount'
//远程加载combox
var combo = Ext.create({
    renderTo: document.body,
    xtype: 'combo',
    queryMode: 'remote',        //远程数据查询
    fieldLabel: 'PandaCombox',
    forceSelection: true,       //强制必须选择
    displayField: 'fullname',   //表单显示的值
    valueField: 'id',           //给表单的值
    minChars: 1,                //自动填充阈值
    triggerAction: 'all',       //一次性读取所有远程数据
    store: remoteData

实例:监听select事件

xtype : 'combobox', fieldLabel: 'Combo box', queryMode: 'local', displayField: 'abbr', valueField: 'name', renderTo: Ext.getBody(), listeners: { //监听事件 select: function(combo,records){ //监听select事件 Ext.Msg.alert('Alert','你选择的是: ' + records.get('abbr')); store: { id : 'statesid', fields: ['abbr', 'name'], data : [ {"abbr":"HTML", "name":"HTML"}, {"abbr":"CSS", "name":"CSS"}, {"abbr":"JS", "name":"JavaScript"}

标签框(tagfield)

Ext.form.field.Tag类型继承自Ext.form.field.ComboBox类型
tagfield类型的xtype为tagfield
tagfield类型类似ComboBox类型,但是Tag类型可以多选,类似多选框
注意:tagfield只有在classic包中存在

实例:基本的Tag标签域

xtype: 'tagfield', fieldLabel: 'Select zone', //Label标签的内容 displayField: 'name', //显示的Store字段 valueField: 'id', //取值的Store字段 filterPickList: true, //选中的不会再显示在下方 queryMode: 'local', //本地查询 store: { //对应的Store fields : ['id','name'], data : [ {id: 1 ,name: 'Zone A' }, {id: 2 ,name: 'Zone B' }, {id: 3 ,name: 'Zone C' }, {id: 4 ,name: 'Zone D' }, {id: 5 ,name: 'Zone E' }

复选框(checkboxfield)

Ext.form.field.Checkbox

xtype: 'fieldcontainer', fieldLabel: 'Check Box Field', defaultType: 'checkboxfield', layout: 'hbox', items: [ boxLabel : 'HTML', inputValue: 'html', flex : 1, margin : '0 8 0 0', id : 'checkbox1' boxLabel : 'CSS', inputValue: 'css', checked : true, flex : 1, margin : '0 8 0 0', id : 'checkbox2' boxLabel : 'JavaScript', inputValue: 'js', flex : 1, margin : '0 8 0 0', id : 'checkbox3'

富文本编辑器(HtmlEditor)

注意:HTML Editor控件只在classic包存在

实例:简单的HTML编辑器

xtype: 'htmleditor', width: 800, height: 200,

实例:开启和关闭工具栏的功能

xtype: 'htmleditor', width: 800, height: 200, enableFontSize: false, //关闭字体大小 enableFont: false, //关闭字体类型

实例:获得内容

xtype: 'htmleditor', width: 800, height: 200, validate: function(){ var value = this.getValue(); //获得内容 console.log(value); listeners: { //绑定事件 click: { fn: 'this.validate'

日期框(datefield)

Ext.form.field.Date
日期框的xtype为datefield

实例:基本日期选择框

xtype: 'datefield', fieldLabel: 'Date picker', //label显示内容 name: 'createDate', //name属性名

实例:自定义日期格式

使用format配置项设置前端显示日期格式
使用submitFormat配置项设置发送到服务器端的日期格式
使用altFormats配置项设置日期的备用格式,用户可以自己选择喜欢输入格式

xtype: 'datefield', fieldLabel: 'Date picker', //label显示内容 name: 'createDate', //name属性名 format: 'Y年m月d日', //前端显示日期的格式 submitFormat: 'Y-m-d', //发送到服务器端的日期格式 altFormats: 'd-m-Y|d m Y|d.m.Y', //备用输入格式

实例:设置日期值

Ext.create('Ext.form.field.Date', {
    fieldLabel: 'Pick a Date',
    renderTo: Ext.getBody(),
    format: 'd/m/Y' //指定格式
//设置值
dateField.setValue('31/01/2011');

实例:禁用指定日期

使用disabledDates配置项即可
注意:disabledDates的格式必须和format的相同

xtype: 'datefield', fieldLabel: 'Date picker', //label显示内容 name: 'createDate', //name属性名 format: 'Y年m月d日', //前端显示日期的格式 submitFormat: 'Y-m-d', //发送到服务器端的日期格式 altFormats: 'd-m-Y|d m Y|d.m.Y', //备用输入格式 disabledDates: ['2021年01月29日','2021年01月28日'], //禁用指定日期 disabledDatesText: '这些日期不可以选择'

实例:设置日期上下限

使用minValue配置项设置日期下限
使用maxValue配置项设置日期上限

xtype: 'datefield', fieldLabel: 'Date picker', //label显示内容 name: 'createDate', //name属性名 format: 'd/m/Y', //前端显示日期的格式 submitFormat: 'Y-m-d', //发送到服务器端的日期格式 minValue: '15/10/2020', //日期下限 maxValue: '31/10/2020', //日期上限

实例:监听select事件

xtype: 'datefield', fieldLabel: 'Date picker', //label显示内容 name: 'createDate', //name属性名 renderTo:document.body, listeners: { //监听事件 select: function(self,selectDate){ //监听select事件 Ext.Msg.alert('Alert','你选择的是: ' + selectDate);

时间框(timefield)

Ext.form.field.Time

实例:简单的时间选择框

xtype: 'timefield', fieldLabel: 'Time field',

实例:指定具体限制参数

xtype: 'timefield', fieldLabel: 'Time field', minValue: '6:00', //指定时间范围(最小) maxValue: '8:00', //指定时间范围(最大) increment: 30, //增量 format: 'H:i', //显示的格式 invalidText: '时间格式错误', //时间格式错误显示文本

单选框(radiofield)

Ext.form.field.Radio
Radio的xype为checkboxgroup

实例:简单的单选框

xtype : 'radiofield', fieldLabel : '性别', //单选框描述 labelWidth: 30, checked: true, //勾选 name: 'sex', //设置HTML的name属性 labelSeparator: ' ', //单选框描述 和 文本 之间的间隔文本 boxLabel : '男', //单选框的文本 inputValue : '1', //单选框的值

单选项组(RadioGroup)

Ext.form.RadioGroup扩展自Ext.form.CheckboxGroup
用于将多个radio组件归为一组

实例:简单的单选框组

xtype : 'radiogroup', width: 450, fieldLabel: 'Sex ', layout: 'hbox', items: [ boxLabel: 'Male', flex: 1, inputValue: '1', name: 'sex', checked: true boxLabel: 'Female', flex: 1, inputValue: '2', name: 'sex',

实例:单选按钮组(三列)

xtype: 'radiogroup', columns: 3, items: [ boxLabel: 'Option 1', name: 'option', inputValue: 1 boxLabel: 'Option 2', name: 'option', inputValue: 2 boxLabel: 'Option 3', name: 'option', inputValue: 3 boxLabel: 'Option 5', name: 'option', inputValue: 5 boxLabel: 'Option 6', name: 'option', inputValue: 6

实例:也是三列,但从下再向右

columns: 3,
vertical: true,

多选框(checkbox)

Ext.form.field.Checkbox
Checkbox的xtype类型为checkboxfield、checkbox
提示:一般将多选框放入到多选框组(CheckboxGroup)

实例:简单的多选框

xtype : 'checkbox', fieldLabel : 'Girl', //复选框描述 labelWidth: 150, //标签宽度 checked: true, //默认勾选 name: 'panda', //HTML的name属性 labelSeparator: ' ', //复选框描述 和 文本 之间的间隔文本 boxLabel : 'Cat', //复选框的文本 inputValue : '1', //复选框的值

实例:多选框组数据来自Store

使用Store数据作为选项
说明:queryMode属性可以设置为local或remote,表示数据更新到本地还是服务器

xtype: 'checkbox', fieldLabel: 'Choose Month', queryMode: 'local', //设置为本地模式 displayField: 'name', valueField: 'abbr', store: { //使用Store的数据 fields: ['abbr', 'name'], data: [ {"abbr":"JAN", "name":"January"}, {"abbr":"FEB", "name":"February"}, {"abbr":"MAR", "name":"March"}, {"abbr":"APR", "name":"April"}, {"abbr":"MAY", "name":"May"}, {"abbr":"JUN", "name":"June"}, {"abbr":"JUL", "name":"July"}, {"abbr":"AUG", "name":"August"}, {"abbr":"SEP", "name":"September"}, {"abbr":"OCT", "name":"October"}, {"abbr":"NOV", "name":"November"}, {"abbr":"DEC", "name":"December"}

多选项组(CheckboxGroup)

Ext.form.CheckboxGroup继承自Ext.form.FieldContainer
CheckboxGroup的xtype为checkboxgroup
CheckboxGroup主要用于将CheckBox组成一组

实例:简单的多选框组

xtype: 'checkboxgroup', fieldLabel: '请选择你会的编程语言', vertical: false, //是否从上到下 columns: 2, //显示为几个列 width: 250, items: [ boxLabel: 'C++', name: 'rb', inputValue: '1', labelWidth: 250, columnWidth: 250, boxLabel: '.Net Framework', name: 'rb', inputValue: '2', columnWidth: 250, checked: true boxLabel: 'C#', name: 'rb', columnWidth: 250, inputValue: '3' boxLabel: 'SQL Server', name: 'rb', columnWidth: 250, inputValue: '4'

实例:简单的多选框组2

Ext.form.CheckboxGroup({
    columns: 2,
    fieldLabel: 'Technologies',
    name: 'technologies',
    style: {
        padding: '5px 10px 5px 10px'
    items: [
            xtype: 'checkbox',
            boxLabel: 'JavaScript',
            name: 'technologies',
            inputValue: 'javascript'
           xtype: 'checkbox',
           boxLabel: 'C#',
           name: 'technologies',
           inputValue: 'c#'
            xtype: 'checkbox',
            boxLabel: 'HTML',
            name: 'technologies',
            inputValue: 'html'
            xtype: 'checkbox',
            boxLabel: 'SQL',
            name: 'technologies',
            inputValue: 'sql'
            xtype: 'checkbox',
            boxLabel: 'Python',
            name: 'technologies',
            inputValue: 'python'
            xtype: 'checkbox',
            boxLabel: 'CSS',
            name: 'technologies',
            inputValue: 'css'

表单域组(FieldContainer)

FieldContainer用于将多个表单域组成一组
FieldContainer还可以用于控制布局
配合布局可以用于包裹多个字段

实例:简单域组

xtype: 'fieldcontainer', fieldLabel: 'Name', //域组标签 layout: { //设置布局 type: 'hbox', align: 'stretch' combineErrors: true, defaultType: 'textfield', defaults: { hideLabel: 'true' items: [ name: 'firstName', fieldLabel: 'First Name', flex: 2, emptyText: 'First', allowBlank: false name: 'lastName', fieldLabel: 'Last Name', flex: 3, margin: '0 0 0 6', emptyText: 'Last', allowBlank: false

验证表单域(field validation)

可以使用vtype设置表单中域必须满足的条件
vtype支持的值:

实例:验证是否邮箱格式

Ext.create('Ext.form.field.Text', {
    renderTo: Ext.getBody(),
    name: 'email',
    fieldLabel: 'Email',
    allowBlank: true,
    vtype: 'email'

按钮(BUTTON)

Ext.button.Button
   xtype: 'button', 
   text : 'Button'

实例:和表单元素放在一起的按钮

Ext.create('Ext.form.Panel',{
    width: 550,
    title: 'PandaTitle',
    renderTo: document.body,
    items: [
            xtype: 'textfield',
            fieldLabel: 'UserName',
            name:'userName'
        //和表单元素放在一起的button
            xtype: 'button',
            text: 'Submit',
            handler: function(){
                console.log('Submit Click');

实例:放在buttons属性中的按钮

Ext.create('Ext.form.Panel',{
    width: 550,
    title: 'PandaTitle',
    renderTo: document.body,
    items: [
            xtype: 'textfield',
            fieldLabel: 'UserName',
            name:'userName'
    buttons: [ //放在buttons属性中的button
            xtype: 'button',
            text: 'Submit',
            handler: function(){
                console.log('Submit');
                //获得表单组件
                var form = this.up('form').getForm();
                //获得表单值
                var value = form.getValues();

类数值框(SPINNER)

Ext.form.field.Spinner
xtype为spinnerfield
注意:SPINNER只存在classic包中
Spinner和number类似,但是number用于选择数字,而spinner可以选择其他内容

实例:自定义显示内容

Ext.define('Ext.ux.CustomSpinner', {
    extend: 'Ext.form.field.Spinner',
    alias: 'widget.customspinner',
    // override onSpinUp (using step isn't neccessary)
    onSpinUp: function() {
        var me = this;
        if (!me.readOnly) {
            // gets rid of " Pack", defaults to zero on parse failure
            var val = parseInt(me.getValue().split(' '), 10) || 0;
            me.setValue((val + me.step) + ' Pack');
    // override onSpinDown
    onSpinDown: function() {
        var me = this;
        if (!me.readOnly) {
           // gets rid of " Pack", defaults to zero on parse failure
           var val = parseInt(me.getValue().split(' '), 10) || 0;
           if (val <= me.step) {
               me.setValue('Dry!');
           } else {
               me.setValue((val - me.step) + ' Pack');