Javascript - ExtJs - Ext.form.Panel组件

FormPanel组件(Ext.form.FormPanel) logogram:Ext.form.Panel | xtype:form

Ext.form.Panel.配置

frame : bool
//指示表单背景色是否使用面板底色,为false则为白色

renderTo : ElementID
//将面板渲染到哪个元素

title : string
//指示标题

width : string
//面板宽度

height : string
//面板高度,默认其宽度可自动适应子组件,无需设置。

style : string
//指示css样式

collapsible:bool
//是否在标题栏显示一个可折叠展开的按钮

labelAlign : 'right' | 'left' | 'center'
//表单子控件前的文本的对齐方式

buttonAlign: 'right' | 'left' | 'top'
//按钮对齐方式

labelWidth : number
//表单子控件前的文本的宽度

defaultType : 'textfield'
//配置了此项后,items子组件中所有是文本框的字段可以不配置xtype,只配置fieldLabel即可。

defaults : { }
//配置了此项后,items子组件都会遵照此配置的样式。
示例:
defaults : { width : }//旗下所有子组件宽度为100px。

fileUpload: true
//显示文件上传组件,如果指示了此项,则必须在items子组件数组中注册一个xtype为"fileuploadfield"的子组件

items : [ {} , { }]
//添加表单子控件

buttons : [ {} , {} ]
//添加表单按钮
buttons: [
        { text: '提交', handler: function () { Ext.MessageBox.alert("", "提交成功"); } },
        { text: "取消", handler: function () { Ext.MessageBox.alert("", "取消成功"); } }
]

tbar | bbar : [ {} , {} ]
//添加上、下工具栏
tbar: [
    { xtype: "button", text: "关闭", handler: function () { Ext.MessageBox.alert("", "正在关闭"); } },
    { xtype: 'tbseparator' },//分隔符
    { xtype: "button", text: "其它", handler: function () { Ext.MessageBox.alert("", "其它操作"); } }
]

config

//创建表单
Ext.create("Ext.form.Panel", {
    id: "formEdit",
    renderTo: "box",
    forceFit: true,
    style: "border:none;padding:10px;",  //去除panel组件dom元素的边框
    border: false, // 去除panel组件的边框
    defaultType: "textfield",
    items: [
            {
                fieldLabel: "标  题", name: "inputText", labelWidth: 
            }
    ],
    buttons: [
        {
            text: "OK",
            handler: function () {
                alert();
            }
        }
    ]
}); //表单面板中也可以将Panel组件作为一个容器子组件使用
items: [
    {
        xtype: "panel",
        style: "……",
        width: "100%",
        items: [
            { xtype: "textfield" }
        ]
    },
    {
        xtype: "panel",
        style: "……",
        width: "100%",
        items: [
            { xtype: "textfield" }
        ]
    }
]

Ext.form.Panel的表单提交方式

Extjs默认使用Ajax提交表单,以下三种表单提交方式各有特点。

Ext.form.BasicForm

Ext.form.Panel是容纳表单控件的容器,其本身是从Ext.Panel派生,如果要获取表单对象则需调用FormPanel的getForm方法找到表单对象(Ext.form.BasicForm),再调用submit方法提交表单。

<script>

Ext.onReady(function () {
    renderTo:"box",
    labelAlign: 'right',
    title: 'box',
    labelWidth: ,
    buttonAlign: 'center',
    frame: true,
    width: ,
    items: [{
        xtype:"textfield",
        id: "userName",
        name: "userName",
        fieldLabel: '文本框'
    }],
    buttons: [{
        text: '提交',
        handler: function () {
            var form = formPanel.getForm();//得到表单对象
            form.submit({ //提交配置
                url: 'AjaxFormHandler.ashx',
                method: 'POST',
                //提交后等待时的弹窗标题和弹窗内容
                waitTitle : "提示",
                waitMsg: '正在提交数据,稍等……',
                //如果http无错误并且服务端response的Json字符中的success为true时的回调函数,如果服务端返回的Json字符不包含success:'true',则此处的success函数不会执行
                success: function (form, action) {
                    //调用action的result可得到从服务端返回的Json格式字符串
                    //data是Json字符串里的一个属性,是你在服务端response的Json格式字符串中定义的属性
                    Ext.Msg.alert('信息',action.result.data);
                },
                //如果http错误时的回调函数
                //如果服务端返回的Json字符中不包含success或success为false时的回调函数
                failure: function (form, action) {
                    //如果http错误时
                    if (action.failureType != Ext.form.Action.SERVER_INVALID)
                        Ext.Msg.alert('信息', "无法连接服务器");
                        //否则认为已经连上服务端,输出服务端的提示信息
                    else
                        Ext.Msg.alert('信息', action.result.errors);
                }
            });
        }
    }]
});

</script>

Ext.form.BasicForm提交

服务端的AjaxFormHandler.ashx:

try
{
    //……
    Response.Write ( "{success:'true',msg:'上传成功'}"); //成功时Json字符必须包含success:'true',否则客户端的failure会执行
}
catch
{
    Response.Write ( "{msg:'上传失败'}" );
}           

服务端

Ext.Ajax.request 

派生自Ext.data.Connection的Ext.Ajax提供了完整的异步请求,可用于提交表单。参看:Javascript - ExtJs - 数据

<script>

Ext.onReady(function () {
        Ext.create("Ext.form.Panel", {
            renderTo: "box",
            labelAlign: 'right',
            title: 'box',
            labelWidth: ,
            buttonAlign: 'center',
            frame: true,
            width: ,
            items: [{
                xtype: "textfield",
                id: "userName",
                name: "userName",
                fieldLabel: '文本框'
            }],
            buttons: [{
                text: '提交',
                handler: function () {
                    var form = formPanel.getForm();//得到表单对象
                    Ext.Ajax.request({
                        method: 'POST',
                        url: 'AjaxFormHandler.ashx',
                        //params提供提交到服务端的参数                 
                        params: form.getValues(true),
                        //http无错误时的回调函数
                        success: function (response) {
                            //Ext.decode解析Json字符串为Json对象
                            var m = Ext.decode(response.responseText);
                            //data是Json字符串里的一个属性,是你在服务端response的Json格式字符串中定义的属性
                            Ext.Msg.alert('信息', m.data);
                        },
                        //http错误时的回调函数
                        failure: function () {
                            Ext.Msg.alert('信息', "无法访问服务器");
                        }
                    });
                }
            }]
        });
    });

</script>

Ext.Ajax.request提交

服务端的AjaxFormHandler.ashx:

try
{
    //……
    Response.Write ( "{msg:'上传成功'}"); //Ext.Ajax.request提交 则成功时Json字符不需要包含success:'true'(可有可无),这与Ext.form.BasicForm提交不一样
}
catch
{
    Response.Write ( "{msg:'上传失败'}" );
}           

服务端

原始html提交(非Ajax提交)

//创建表单
Ext.create("Ext.form.Panel", {
    id: "formLogin",
    url: "/Home/ValidateValidLogin", //action地址
    standardSubmit: true, //设为标准提交,即html表单提交
    border: false, // 去除panel组件的边框
    defaultType: "textfield",
    defaults: { style: "margin-top:10px;" },
    layout: {
        type: 'vbox',
        align: 'center'
    },
    items: [
            {
                name: "name",                
                emptyText: "用    户"
            },
            {
                name: "pwd",
                emptyText: "密    码"
            },
            {
                xtype: "button",
                text: "登  入",
                handler: function () {
                    var form = Ext.getCmp("formLogin").getForm();
                    form.method = "post";
                    form.submit();
                }
            }
    ]
});

原始Html提交

Ext.form.Panel子组件

子组件通用配置

id: string
//组件的、组件对应dom元素的id。

name: string
//组件的、组件对应dom元素的name。

fieldLabel: string
//框前显示的文本

value: string
//显示在框中的值

labelWidth: string
//各种框前面的文本宽度

labelAlign: 'left' | 'right' | 'top'
//各种框前面的文本的对齐方式

allowBlank: bool
//是否允许空值

blankText: string
//空值时的提示信息

padding:cssString
//设置css内边距

margin:cssString
//设置css外边距

style:cssString
//设置css样式
//示例:
{ xtype:"textfield",style:"margin:0 10px" }

config

子组件通用方法

getFieldLabel()
//获取Label的文本

setFieldLabel(val)
//设置Label的文本

getValue()
//获取域的值

setValue()
//设置域的值

method

文本框

全名:Ext.form.field.Text | Ext.form.field.TextArea | Ext.form.field.Number | Ext.form.field.Display | Ext.form.field.File | Ext.form.field.Hidden

xtype:'textfield'(普通) |  'textarea'(多行) | 'numberfield'( 数字)| 'displayfield'(只读文本)| 'fileuploadfield'(文件上传域)| hiddenfield(隐藏域)

文本框配置

emptyText
//空值时的默认文本

readOnly:bool
//是否只读
 
hideEmptyLabel:bool
//隐藏为空的fieldLabel,true时完全隐藏,false仅隐藏但保留空白占位
示例:
{ xtype: "displayfield", fieldLabel: "", hideEmptyLabel: true }//
 
hideLabel:bool
//无视fieldLabel是否为空都要隐藏它,true时完全隐藏,false仅隐藏但保留空白占位
 
inputType: password
//密码框
 
allowDecimals: bool
//是否允许小数。
 
allowNegative: bool
//是否允许负数。
 
nanText: string
//非数字时的提示信息,只要用户输入错误的字符都会被立即自动删除,提示信息几乎不会显示。
 
decimalPrecision:number
//精确到小数点后两位。
 
grow: true,
//允许文本框自动增长以适应文字的输入
 
preventScrollbars: true
//隐藏滚动条,需要同时设置grow为true才生效。
 
value:string | number
//框的值
示例:
{ xtype: "displayfield", fieldLabel: "只读",value:"此项没有输入框" }
 
fieldStyle:cssString
//文本框的css样式
示例:
{ xtype: "displayfield", value: "未选择任何权限", hideLabel: true, labelWidth: , fieldStyle:"color:white;", style: 'color:white;background:red;'};
 
LabelStyle:cssString
//文本框前的文本的css样式
 
/*------属性------*/
inputEl
//获取表单组件自身的输入框的Element元素,只有具备输入框的组件才有此属性,可通过component.inputEl.dom.value获取输入框的值

emptyText
//获取空值时的默认文本
    
/*------方法------*/
setFieldStyle(cssString)
//设置css样式

Config

只读文本

{
    xtype: "displayfield",
    fieldLabel:"提示",
    value:"纯文本" //value会以纯文本显示在表单上
} //从服务端获取数据后动态插入纯文本,Ajax提交表单就不用说了,在success中直接插入错误提示文本,如果是非Ajax提交表单可采取以下方式显示错误提示
var errorTip ="@ViewData["errorTip"]";
if (errorTip != "") {
    var error = { xtype: "displayfield", value: "<font color='red'>" + errorTip + "</font>" };
    Ext.getCmp("formLogin").insert(, error);
}

密码框

{ fieldLabel: "密  码",xtype:"textfield",inputType:"password" }
Ext.util.MD5 = function (s, raw, hexcase, chrsz) {
    raw = raw || false;
    hexcase = hexcase || false;
    chrsz = chrsz || ;

function safe_add(x, y) {
        var lsw = (x & 0xFFFF) + (y & 0xFFFF);
        var msw = (x >> ) + (y >> ) + (lsw >> );
        return (msw << ) | (lsw & 0xFFFF);
    }
    function bit_rol(num, cnt) {
        return (num << cnt) | (num >>> ( - cnt));
    }
    function md5_cmn(q, a, b, x, s, t) {
        return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
    }
    function md5_ff(a, b, c, d, x, s, t) {
        return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
    }
    function md5_gg(a, b, c, d, x, s, t) {
        return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
    }
    function md5_hh(a, b, c, d, x, s, t) {
        return md5_cmn(b ^ c ^ d, a, b, x, s, t);
    }
    function md5_ii(a, b, c, d, x, s, t) {
        return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
    }

function core_md5(x, len) {
        x[len >> ] |= 0x80 << ((len) % );
        x[(((len + ) >>> ) << ) + ] = len;
        var a = ;
        var b = -;
        var c = -;
        var d = ;
        for (var i = ; i < x.length; i += ) {
            var olda = a;
            var oldb = b;
            var oldc = c;
            var oldd = d;
            a = md5_ff(a, b, c, d, x[i + ], , -);
            d = md5_ff(d, a, b, c, x[i + ], , -);
            c = md5_ff(c, d, a, b, x[i + ], , );
            b = md5_ff(b, c, d, a, x[i + ], , -);
            a = md5_ff(a, b, c, d, x[i + ], , -);
            d = md5_ff(d, a, b, c, x[i + ], , );
            c = md5_ff(c, d, a, b, x[i + ], , -);
            b = md5_ff(b, c, d, a, x[i + ], , -);
            a = md5_ff(a, b, c, d, x[i + ], , );
            d = md5_ff(d, a, b, c, x[i + ], , -);
            c = md5_ff(c, d, a, b, x[i + ], , -);
            b = md5_ff(b, c, d, a, x[i + ], , -);
            a = md5_ff(a, b, c, d, x[i + ], , );
            d = md5_ff(d, a, b, c, x[i + ], , -);
            c = md5_ff(c, d, a, b, x[i + ], , -);
            b = md5_ff(b, c, d, a, x[i + ], , );
            a = md5_gg(a, b, c, d, x[i + ], , -);
            d = md5_gg(d, a, b, c, x[i + ], , -);
            c = md5_gg(c, d, a, b, x[i + ], , );
            b = md5_gg(b, c, d, a, x[i + ], , -);
            a = md5_gg(a, b, c, d, x[i + ], , -);
            d = md5_gg(d, a, b, c, x[i + ], , );
            c = md5_gg(c, d, a, b, x[i + ], , -);
            b = md5_gg(b, c, d, a, x[i + ], , -);
            a = md5_gg(a, b, c, d, x[i + ], , );
            d = md5_gg(d, a, b, c, x[i + ], , -);
            c = md5_gg(c, d, a, b, x[i + ], , -);
            b = md5_gg(b, c, d, a, x[i + ], , );
            a = md5_gg(a, b, c, d, x[i + ], , -);
            d = md5_gg(d, a, b, c, x[i + ], , -);
            c = md5_gg(c, d, a, b, x[i + ], , );
            b = md5_gg(b, c, d, a, x[i + ], , -);
            a = md5_hh(a, b, c, d, x[i + ], , -);
            d = md5_hh(d, a, b, c, x[i + ], , -);
            c = md5_hh(c, d, a, b, x[i + ], , );
            b = md5_hh(b, c, d, a, x[i + ], , -);
            a = md5_hh(a, b, c, d, x[i + ], , -);
            d = md5_hh(d, a, b, c, x[i + ], , );
            c = md5_hh(c, d, a, b, x[i + ], , -);
            b = md5_hh(b, c, d, a, x[i + ], , -);
            a = md5_hh(a, b, c, d, x[i + ], , );
            d = md5_hh(d, a, b, c, x[i + ], , -);
            c = md5_hh(c, d, a, b, x[i + ], , -);
            b = md5_hh(b, c, d, a, x[i + ], , );
            a = md5_hh(a, b, c, d, x[i + ], , -);
            d = md5_hh(d, a, b, c, x[i + ], , -);
            c = md5_hh(c, d, a, b, x[i + ], , );
            b = md5_hh(b, c, d, a, x[i + ], , -);
            a = md5_ii(a, b, c, d, x[i + ], , -);
            d = md5_ii(d, a, b, c, x[i + ], , );
            c = md5_ii(c, d, a, b, x[i + ], , -);
            b = md5_ii(b, c, d, a, x[i + ], , -);
            a = md5_ii(a, b, c, d, x[i + ], , );
            d = md5_ii(d, a, b, c, x[i + ], , -);
            c = md5_ii(c, d, a, b, x[i + ], , -);
            b = md5_ii(b, c, d, a, x[i + ], , -);
            a = md5_ii(a, b, c, d, x[i + ], , );
            d = md5_ii(d, a, b, c, x[i + ], , -);
            c = md5_ii(c, d, a, b, x[i + ], , -);
            b = md5_ii(b, c, d, a, x[i + ], , );
            a = md5_ii(a, b, c, d, x[i + ], , -);
            d = md5_ii(d, a, b, c, x[i + ], , -);
            c = md5_ii(c, d, a, b, x[i + ], , );
            b = md5_ii(b, c, d, a, x[i + ], , -);
            a = safe_add(a, olda);
            b = safe_add(b, oldb);
            c = safe_add(c, oldc);
            d = safe_add(d, oldd);
        }
        return [a, b, c, d];
    }
    function str2binl(str) {
        var bin = [];
        var mask = ( << chrsz) - ;
        for (var i = ; i < str.length * chrsz; i += chrsz) {
            bin[i >> ] |= (str.charCodeAt(i / chrsz) & mask) << (i % );
        }
        return bin;
    }
    function binl2str(bin) {
        var str = "";
        var mask = ( << chrsz) - ;
        for (var i = ; i < bin.length * ; i += chrsz) {
            str += String.fromCharCode((bin[i >> ] >>> (i % )) & mask);
        }
        return str;
    }

function binl2hex(binarray) {
        var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
        var str = "";
        for (var i = ; i < binarray.length * ; i++) {
            str += hex_tab.charAt((binarray[i >> ] >> ((i % ) *  + )) & 0xF) + hex_tab.charAt((binarray[i >> ] >> ((i % ) * )) & 0xF);
        }
        return str;
    }
    return (raw ? binl2str(core_md5(str2binl(s), s.length * chrsz)) : binl2hex(core_md5(str2binl(s), s.length * chrsz)));
};

ExtJs MD5加密

var md5Password = Ext.util.MD5(v); //加密密码

文件上传框

注意一点,当你使用Ext.form.Basic对象的getValues方法获取表单数据时,这并不会包含文件上传域的值,所以,将文件上传域放在有其它输入框的表单中时也不会影响正常提交表单,文件上传域可单独开启Ajax请求执行上传。

<script>

Ext.create("Ext.form.Panel", {
        //……
        id:"employeeEntryForm",
        fileUpload: true, //此处开启文件上传
        items: [
            {
                fieldLabel: "照  片",
                xtype: "fileuploadfield",
                id: "userHeaderImg",
                emptyText: '选择图片',
                buttonText: '浏览'
            },
            {
                text: "上传",
                xtype: "button",
                id: "fileBtn",
                handler: function () {
                    var form = Ext.getCmp("employeeEntryForm").getForm();
                    var filePath = form.findField("userHeaderImg").getValue();
                    //后缀
                    var backName = filePath.substring(filePath.lastIndexOf(".") + ).toLocaleLowerCase();
                    //测试文件后缀
                    if ($(document).trim(filePath) == ) {
                        Ext.Msg.alert("提示", "未选择图片");
                        return;
                    }
                    else if (backName != "jpg" && backName != "png" && backName != "gif") {
                        Ext.Msg.alert("提示", "只能上传jpg、png、gif");
                        return;
                    }
                    //发起上传
                    form.submit({
                        clientValidation: true, //true时将同时验证表单其它项是否已通过vType或validator验证,false则不验证
                        url: '/Ashx/FileUpLoadHandler.ashx',
                        //params: { upLoadType: "userHeaderImg" }, 可以附加参数
                        waitMsg: '正在上传...',
                        success: function (form, action) {
                            Ext.Msg.alert('提示', action.result.msg);
                        },
                        failure: function (form, action) {
                            switch (action.failureType) {
                                case Ext.form.action.Action.CLIENT_INVALID:
                                    Ext.Msg.alert('错误', '表单其它项没有录入数据,无法上传'); //表单其它项未通过vType或validator验证时会自动阻止上传并提示错误信息
                                    break;
                                case Ext.form.action.Action.CONNECT_FAILURE:
                                    Ext.Msg.alert('错误', 'Ajax通讯失败');
                                    break;
                                case Ext.form.action.Action.SERVER_INVALID:
                                    Ext.Msg.alert('错误', action.result.msg);
                            }
                        }
                    });
                }
            }
        ]
    });

</script>

客户端

public void ProcessRequest( HttpContext context )
{
    var Response = context.Response;
    var Request = context.Request;
    Response.ContentType = "text/plain";

HttpFileCollection files = HttpContext.Current.Request.Files;
    HttpPostedFile postedFile = files [  ];
    string fileName = postedFile.FileName;
    string suffix = fileName.Substring ( fileName.LastIndexOf ( '.' ) );
    System.Text.StringBuilder s = new System.Text.StringBuilder ( );

s.Append ( "~/Img/userHeaderImg/" ).Append ( DateTime.Now.ToString ( "yyyyMMddHHmmss" ) ).Append ( "." ).Append ( suffix );
    string absolutePath = context.Server.MapPath ( s.ToString ( ) );
    try
    {
        postedFile.SaveAs ( absolutePath );
        Response.Write ( "{success:'true',msg:'上传成功'}" ); //此处注意,因为是使用的form.Basic提交上传,所以成功上传后返回的Json字符中必须包含success:'true',否则无论上传成功与否都会执行failure
    }
    catch
    {
        Response.Write ( "{msg:'上传失败'}" );
    }
}

服务端

下拉框

全名:Ext.form.field.Combobox | Ext.form.field.Time | Ext.form.field.Date

xtype:'combobox'(普通)| 'timefield'(时间)| 'datefield'(日期)

下拉框配置

id : string
//配置此项则同时自动为组件的ID和配套的隐藏域的name设置同样的string。

name : string
//配置此项则同时自动为隐藏域的name设置同样的string。

width : number
//宽

triggerAction : "all" | "query"
//all显示全部下拉列表项,如果设为query,则加载后只有一次机会会显示全部列表,等用户选中某个数据后,下拉列表会自动删除未被选中的数据,只保留被选中的数据。

emptyText : string
//灰色的文本提示。

blankText : string
//没有选择时提示错误信息

editable : bool
//是否可编辑。

readOnly : bool
//禁用。

displayField : "key" | "value"
//指示下拉框显示的数据是key还是value。

valueField : "key" | "value"
//指示下拉框数据的值是key还是value。

hiddenName : string
//下拉框被选中后,其选项的value会赋值给对应的自动生成的隐藏域,这样才能获取到下拉框的值,此hiddenName的值必须与combobox的ID或者name一样,否则找不到下拉框的值。

mode: "local" | "remote"
//指示数据来源是本地还是服务器,如果不指示此属性,则数据源需要load()加载一次,指示了此属性可自动load,如果已经设为remote,而store也load,则store会重复load两次。

store : Ext.data.DataStore
//指示数据来源,下拉框的数据来源要么是服务端要么是本地,通过store属性指定,store指向一个派生自Ext.data.Store类的实例表示数据源。经测试数据源最好在编辑器外部指示,也即不要使用store:{xtype:"xxxStore"}去定义。如果这样定义就可能会出现问题。

typeAhead: true
//启用延时查询。

typeAheadDelay: millisecond
//延时毫秒,默认250。

配置.config

<script>

Ext.create("Ext.data.ArrayStore", {
        storeId: "jobState",
        fields: ['key', 'value'],
        data: [
            ['在职', '1'],
            ['离职', '0']
        ]
    });

{ fieldLabel: "在  职", xtype: 'combobox', id: 'jobState', displayField: 'key', valueField: 'value', emptyText: "------选择------", allowBlank: false, blankText: "未选择", editable: false, hiddenName: "jobState", mode: "local", store: "jobState" },

</script>

数据源为本地数据

script type="text/javascript">

Ext.define("AdminRole", {
        extend: "Ext.data.Model",
        fields: [
            { name: "Id", type: "int" },
            { name: "Name", type: "string" }
        ]
    })

Ext.create("Ext.data.Store", {
        storeId: "AdminRoleDataStore",
        autoLoad: true,
        model: "AdminRole",
        proxy: {
            type: "ajax",
            url: "AdminAdminRoleHandler.ashx",
            reader: {
                type: "json",
                root: "ds" //如果Json格式带根,此处要指定根,如{ "ds" : [ { record1 : "" } , { record2 : "" } ] }
            }
        }
    });

{ xtype: "combobox", id: "roleCombo", store: "AdminRoleDataStore", mode: "remote", triggerAction: "all", displayField: "Name", valueField: "Id", editable: false }

</script>

数据源为服务端数据

在下拉框的输入框中嵌入图标

this.setFieldStyle("background: url(/Img/Ico/search.png) no-repeat 8px center;padding-left:26px;");

获取下拉框的输入框中的数据

this.getValue(); //获取value
this.getRawValue(); //获取key,通常是输入框显示的文本
this.setValue(); //设置value
this.setRawValue(); //设置key

下拉框智能提示,查询分页参考:Javascript - ExtJs - 组件 - 分页

单选/复选框

全名:Ext.form.field.Checkbox | Ext.form.field.Radio

xtype:'checkbox'(复选框)| 'radio'(单选框)

配置

boxLabel: string
//选框前的文本,不要使用fieldlabel,后者会离选框很远而不是靠近选框

checked: true
//默认选中

name: string
//所有单选按钮的name必须相同,否则会变成多选

inputValue: string
//项的值

disabled:bool
//是否禁用,禁用后复选框会变成灰色,复选框的readOnly没啥效果,考虑用这个

config

getValue()
//是否被选中

setValue(bool)
//设置选择状态 true为选中

boxLabel
//获取复选框文本

inputValue
//获取复选框的值

property&method

//在formPanel中的checkbox子项
items: [
    { xtype: "checkbox", boxLabel: "计算机", name: "computer", inputValue: "j" },
    { xtype: "checkbox", boxLabel: "音乐", name: "music", inputValue: "y" }
]

var checkedboxs = Ext.getCmp("formEdit").items;
checkedboxs.each(function (box) {
    if (box.getValue()) {
        alert("项:" + box.boxLabel + "  值:" + box.inputValue);
    }
});

复选框取值

单选/复选组

全名:Ext.form.field.CheckboxGroup | Ext.form.field.RadioGroup

xtype:'checkboxgroup'(复选组)| 'radiogroup'(单选组)

配置

fieldLabel: string
//选项组前面的文字

columns: number
//默认一行布满后才换行,除非指示此属性。1时布满一个复选框即换行,2是布满两个即换行,以此类推

items: []
//添加单选或复选框组件

config

Ext.create("Ext.form.Panel", {
    id: "AuthorizationForm",
    forceFit: true,
    layout: "anchor",
    border: false,                   
    items: [
            {
                xtype: "panel",
                style: "padding:10px;",
                height:,
                autoScroll:true,
                anchor: "100%",
                border:false,
                html: html, 
            },
            {
                xtype: "panel",
                style: "padding:10px;",
                border: false,
                anchor: "100%",
                layout: "anchor",
                items: [
                    {
                        xtype: "checkboxgroup", 
                        fileLabel: "选择赋予员工的权限", 
                        anchor: "100%", 
                        layout: 'auto',
                        defaults:{style:"display:inline-block !important;margin-right:10px !important;"},
                        items: [
                            { xtype: "checkbox", boxLabel: "计算机", name: "se1", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "哲学", name: "se2", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "音乐", name: "se3", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "芒果", name: "se4", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "图灵", name: "se5", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "宗教", name: "se6", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "尼采", name: "se7", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "存在主义", name: "se8", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "打火机", name: "se9", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "吴哥窟", name: "se10", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "苦行僧", name: "se11", inputValue: "" },
                            { xtype: "checkbox", boxLabel: "五号人格", name: "se12", inputValue: "" }
                        ]
                    }
                ]
            }                                    
    ],
    buttons: [
        {
            text: "OK",
            handler: function () {
                Ext.getCmp("winEdit").destroy();
            }
        }
    ]
});

demo

Javascript - ExtJs - Ext.form.Panel组件

listeners: {
    //渲染后从服务端取权限
        afterrender: function () {
            var me = this;                                  
            Ext.Ajax.request({
                url: "/UserRight/AjaxShowTbRightTable",
                success: function (r) {                                            
                    var m = Ext.decode(r.responseText);  //Json数组                                          
                    Ext.each(m, function (r) {                                           
                        var checkbox = { xtype: "checkbox", boxLabel: r.RightName, inputValue: r.TbRightId }; //这不是dataModel不能get("property"),用Json.property即可                                        
                        me.query("checkboxgroup[id='tbrightGroup']")[].add(checkbox); //每个容器组件都有add、insert方法                                 
                    });
                }
            });
        }
}

从服务端获取复选框数据

//在formPanel中的checkboxgroup中的checkbox子项
items: [
    {
        xtype: "checkboxgroup", fileLabel: "知识",
        items: [
            { xtype: "checkbox", boxLabel: "计算机", name: "se1", inputValue: "j" },
            { xtype: "checkbox", boxLabel: "音乐", name: "se2", inputValue: "y" }
        ]
    }
]

//取值
var group = Ext.getCmp("formEdit").child("checkboxgroup");
//获取组里所有被选中的项
//注意:假设当前复选组里包含了后代复选组,后代复选组如果有项被选中,则也会被获取
//也即,一个父复选组下无论有多少子复选组,只要被选中,getChecked都会将被选中的checkbox返回
var checkboxs = group.getChecked();
checkboxs.forEach(function (box) {
    alert("项:" + box.boxLabel + "  值:" + box.inputValue);
});

复选组取值

/*
使复选框组实现全选、全取消
IsCancel:true 全取消
*/
function SetGroupCheckSwitch(xCheckboxGroup, checkType) {
    var bool = Object.prototype.toString.call(xCheckboxGroup) === "[object String]";
    var checkboxGroup = bool ? Ext.getCmp(xCheckboxGroup) : xCheckboxGroup;
    if (!checkboxGroup) { return; }
    checkboxGroup.items.each(function (checkBox) {
        //全选
        if (checkType == "all") {
            checkBox.setValue(true);
        }
            //全取消
        else if (checkType == "cancel") {
            checkBox.setValue(false);
        }
            //反选
        else {
            if (checkBox.getValue()) { checkBox.setValue(false); }
            else { checkBox.setValue(true); }
        }
    });
}

/*-----测试-----*/
items: [
    {
        xtype: "button",
        text: "选择全部",
        style: "margin-right:10px;",
        handler: function () {
            var groupCmp =Ext.getCmp("checkBoxGroup");
            if (this.getText() == "选择全部") {
                SetGroupCheckSwitch(groupCmp, "all"); //all全选
                this.setText("全部取消");
            }
            else {
                SetGroupCheckSwitch(groupCmp, "cancel"); //cancel全取消
                this.setText("选择全部");
            }
        }
    },
    {
        xtype: "button",
        text: "反  选",
        handler: function () {
            var groupCmp = this.up("panel").nextSibling().child();
            SetGroupCheckSwitch(groupCmp); //反选不提供checkType即可
        }
    }
]

复选组的全选反选与取消

分组框

全名:Ext.form.FieldSet

xtype:'fieldset'(表单分组)

其实就是一个比较好看的框而已,通过配置它的items,就可以将formPanel的子组件放进去显示。一旦使用了分组框则所有表单子组件都必须分组在分组框里,否则没有放进分组框的组件不会显示。

title: string
//指示标题

width
//指示宽度

height
//指示高度,默认自适应子组件的增长。

labelWidth: number
//各种框前面的文本宽度

collapsible: bool
//是否可收拢、展开

items: [{}, {}]
//添加子组件

config

items: [{
    xtype: "fieldset",
    title: "login",
    width: ,
    collapsible: true,//可收拢、扩展
    items: [
        {
            xtype: "textfield",
            fieldLabel: 'user',
            width: 
        },
        {
            xtype: "textfield",
            fieldLabel: 'password',
            width: 
        }
    ]
}]

demo

renderTo: "box",
title: 'box',
frame: true,
width: ,
items: [{
    xtype: "fieldset",
    title: "choose philosopher",
    width: ,
    items: [
        {
            xtype: "checkboxgroup",
            fieldLabel: "选择哲学家",
            columns: , //一行布满后自动换行,1是布满一个复选框即换行,2是布满两个即换行,以此类推
            items: [
                {
                    xtype: "checkbox",
                    boxLabel: '尼采'
                },
                {
                    xtype: "checkbox",
                    boxLabel: '康德',
                    checked: true
                },
                {
                    xtype: "checkbox",
                    boxLabel: '维特根斯坦'
                }
            ]
        }
    ]
}]

分组框+复选框.demo

表单验证

ExtJs自带验证

为字段配置vtype即可,值请查询官方API。我不喜欢自带的验证功能,只推荐测试空值的配置。

var columns = [
    {
        header: "用户", dataIndex: "user",
        editor: {
            xtype: "textfield",
            allowBlank: false,//是否允许空值
            blankText: "不能为空" //空值时的提示信息
        }
    }
]

自定义验证

方式1:注册vtype自定义验证。也不建议使用这破玩意儿,因为它只能验证一种逻辑,如果你既想测试字符长度又想测试是否包含特殊字符,这种方式就根本做不到。

//自定义验证格式
//配置编辑器时使用vtype:fn1或fn2指向验证程序
Ext.apply(Ext.form.VTypes, {
    fn1: function () { }, fn1Text: "",
    fn2: function () { }, fn2Text: ""
});

//示例:
Ext.apply(Ext.form.field.VTypes, {
    //  自定义验证函数,错误返回false,val是输入框的值,field是输入框组件
    TestLen: function (val, field) {
        return TestLen(, , val);
    },
    // 错误时的提示信息,函数名Text
    TestLenText: '只能介于6-20个字符之间,中文算2个字符'
});

方式2:配置字段的validator,推荐。 使用validator就不要再使用vtype,否则会引起混乱。

{
    fieldLabel: "备    注",
    name: "RightName",
    validator: function (v) {
        var IsNull = $(document).TestEmpty(v);
        var len = $(document).getStrLen(v);
        return IsNull ? "未填写备注" : len <  ? "备注太短" : len >  ? "备注太长" : true;
    }
}

emptyText的问题

Javascript - ExtJs - Ext.form.Panel组件

这个输入框的数据是emptyText,如果你对它使用了验证,那么当它失去焦点时就会触发验证,比如触发一个空值的验证,那么当用户不做更改但同时它可能又确实点击过此项,那么验证就会开启,当提交表单时,表单的IsValid也会阻止提交数据。现在的问题在于,也许你是想当用户在不做改动时就直接提交此项的emptyText,或者你不想直接提交emptyText只提交脏数据,但是用户不做改动但失焦验证却被触发了,其它输入框的数据被改过后成为脏数据,你可以收集,但是这个手机号的输入框却是既没有被污染过但同时它也没有通过验证,没有通过验证则isValid会阻止你提交数据。此时怎么办呢?答案是在validator中重写判断逻辑。

{
    fieldLabel: "手机", id: "Mobile", emptyText: record.get("Mobile"),
    validator: function (v) {                                            
        var phone = $(document).TestPhone(v); //测试是否是手机号
        var IsNull = $(document).TestEmpty(v); //测试是否是空值
        if (IsNull) {
            return true; //是空则验证通过
        }
        else {
            if (!phone) { return "不是手机号" }
            else { return true; }
        }
    }
}

表单对象.Ext.form.Basic

FormPanel是一个表单的容器,它包含了一个Ext.form.Basic的表单对象,通过FormPanel的getForm()方法可以得到它。但它并不是Dom表单对象,Ext.form.Basic提供了一些获取表单元素、检查输入值和提交表单的方法。 而Ext.form.Basic又包含了Ext.form.field.Field(字段)。FormPanel这个层级关系是这样:Ext.form.FormPanel→Ext.form.Basic→Ext.form.field.Field。

isValid()
//测试所有配置了vtype或validator验证的表单字段是否都已经通过了验证。

reset()
//重置表单填入的数据。

submit({})
//以Ajax的方式提交表单。此方法简化了Ext.Ajax.request()方法,参看本页的Ext.form.BasicForm提交表单一节。不推荐使用。另外,如果需要原始的表单提交方式,需要将Ext.form.Basic转化为dom元素。

getValues(asString,dirtyOnly,EmptyText)
//asString:true时,会自动将表单字段全部编码为urlCode
//dirtyOnly:true时,只有被dirty的字段会被提交
//EmptyText:true时,字段没有数据时,其配置的emptyText将被提交。
//获取表单字段的所有数据。数据将被封装在Json匿名对象中,输入框的name作为属性,输入框的值作为value,如:
{ name:"sam",age:}
 //下拉框的值和下拉框所对应的隐藏域的值会作为一个属性被创建,但带有-inputEl后缀 如:
{gender-inputEl:,departmentId-inputEl:}
//如果把这样的Json数据提交到服务端,服务端就无法反序列化为实体对象,而且今天发现有时候表单的非下拉框元素也会自带-inputEl后缀,所以使用getValues时最好做下处理
//示例:
//删除通过form.getValues或form.getFieldValues获取到的Json里带有-inputEl后缀的属性并重新创建对应的不带后缀的属性
//最后返回这个已被格式化的Json
function deleteExtFormPropertyEl(json){
    for(var p in json) {
        var propertyName = p.toString();
        if (propertyName.indexOf("-inputEl") != -) {
            json[propertyName.replace("-inputEl", "")] = json[p];
            delete json[p];
        }
    }
    return json;
}
var form = Ext.getCmp("emFormEdit").getForm();
var formJson=form.getValues();
formJson=deleteExtFormPropertyEl(formJson);
formJson = Ext.encode(formJson);

Ext.Ajax.request({
    method: "post",
    url: "/Personnel/EmployeeEntry",
    params: { data: formJson },
    //……
});

//在服务端通过Json.Net提供的反序列化方法即可将Json数据转换为服务端的对象
@{    
    public ContentResult EmployeeEntry( string formJson )
    {
        string msg = "操作失败";
        try
        {
            var DBContext = new DataAccess.ErpContext ( );
            ErpModels.UserManager user =Newtonsoft.Json.JsonConvert.DeserializeObject<ErpModels.UserManager> ( formJson );
            DBContext.UserManagers.Add ( user );
            DBContext.SaveChanges ( );
            msg = "操作成功";
        }
        catch { }
        return Content ( "{msg:'" + msg + "'}" );
    }
}

getFieldValues()
//只获取输入框类型(包括下拉框)的数据。数据将被封装在Json匿名对象中,输入框的name作为属性,输入框的值作为value,但似乎有时候也带有-inputEl后缀

findField(fieldName)
//fieldName:表单字段的ID或name(包括隐藏域)
//获取指定的字段(Ext.form.field.Field)。获得字段,再调用字段的getValue()方法就可以得到字段的值。*如果是获取下拉框类型的值,则这样调用:findField(下拉框的hiddenName).getValue(),hiddenName必须与下拉框的ID或name同名。否则无法获取下拉框的值
//字段具备setValue属性,当需要使用一个displayField字段时,你可能想利用它来显示一些特殊的信息,如:
//示例:
var columnMsg = form.findField("columnMsg");
columnMsg.setValue("<font color='red'>←还没选择发布到哪个栏目</font>");

method

表单相关操作

统一验证时的提示信息的显示方式

表单所有的错误提示信息的显示由下面代码创建,在form.Field.prototype原型上统一设置提示信息显示方式后就不需要在每一个编辑器都配置一个msgTarget,达到化繁为简的目的。

new Ext.QuickTips.init();//初始化提示信息类
Ext.form.Field.prototype.msgTarget = "title";//显示验证提示信息时为title模式

修改记录并按需更新

如果使用了Entity Framework,那么在客户端填写表单修改记录时,表单本身从数据库读出了原来的记录并填充数据在表单控件上,使用Extjs提交的是被改动过的数据,未被改动的则不会提交。这是通过表单的getValues方法返回的Json数据。这个Json被提交给服务端,服务端将Json转化为实体,那么未提交的数据变成实体的属性后,这些属性就是一个一个的null值,所以没有办法将这个实体copy给数据库已经存在的记录,现在如何将不是null的属性赋值给根据主键查询出的Entity实例?解决思路是在客户端处理Json数据,将属性名打包成数组。将属性值也打包成数组往服务端发送,服务端根据主键查出Entity对象,将数组中的属性名与Entity实体对象的属性名做比较,如果名字相同则说明需要更新该属性的值,这可以利用反射完成对属性值的更改。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;

namespace WebErp.App_Code
{
    public class Yin
    {
        /// <summary>
        /// 将实体的属性利用反射修改为参数提供的值
        /// </summary>
        /// <typeparam name="Old">Enityt实体类型</typeparam>
        /// <param name="old">未改动前的Enityt实体对象</param>
        /// <param name="dirtyPropertyNames">一个以逗号隔开的属性名的字符串</param>
        /// <param name="dirtyPropertyValues">一个以逗号隔开的属性值的字符串</param>
        public static void PhantomPropertyValueReset<Old>(Old old, string dirtyPropertyNames , string dirtyPropertyValues )
        {
            string [ ] dirtyValue = dirtyPropertyValues.Split ( ',' );
            string [ ] dirtyName = dirtyPropertyNames.Split ( ',' );
            for ( int i =  ; i < dirtyName.Length ; i++ )
            {
                Type xtype = old.GetType ( );
                foreach ( PropertyInfo p in xtype.GetProperties ( ) )
                {
                    string name = dirtyName [ i ];
                    if ( p.Name != name ) { continue; }
                    if ( p.PropertyType == typeof ( DateTime? ) )
                    {
                        System.ComponentModel.NullableConverter nullconvert = new System.ComponentModel.NullableConverter ( typeof ( DateTime? ) );
                        xtype.GetProperty ( name ).SetValue ( old , nullconvert.ConvertFromString ( dirtyValue [ i ] ) );
                        continue;
                    }
                    else if( p.PropertyType == typeof ( DateTime ) )
                    {
                        xtype.GetProperty ( name ).SetValue ( old , Convert.ToDateTime( dirtyValue [ i ] ) );
                        continue;
                    }
                    else if( p.PropertyType == typeof ( int? ) )
                    {
                        System.ComponentModel.NullableConverter nullconvert = new System.ComponentModel.NullableConverter ( typeof ( int? ) );
                        xtype.GetProperty ( name ).SetValue ( old , nullconvert.ConvertFromString ( dirtyValue [ i ] ) );
                        continue;
                    }
                    else if ( p.PropertyType == typeof ( int ) )
                    {
                        xtype.GetProperty ( name ).SetValue ( old , Convert.ToInt32 ( dirtyValue [ i ] ) );
                        continue;
                    }
                    else if ( p.PropertyType == typeof ( bool ) )
                    {                        
                        xtype.GetProperty ( name ).SetValue ( old , Convert.ToBoolean ( dirtyValue [ i ] ) );
                        continue;
                    }
                    xtype.GetProperty ( name ).SetValue ( old , dirtyValue [ i ] );
                }
            }
        }
    }
}

反射修改实体属性

{
    text: "保存修改", handler: function () {                                      
        var form = Ext.getCmp("emFormEdit").getForm();
        if (!form.isValid()) { return; }
        var jsonDirty = form.getValues(false, true);//参数2为true表示只获取表单中被修改过的数据

if (jQuery.isEmptyObject(jsonDirty)) {
            Ext.Msg.alert("", "未作任何改动");
            return;
        }

//删除通过form.getValues或form.getFieldValues获取到的Json里带有-inputEl后缀的属性并重新创建对应的不带后缀的属性
        //最后返回这个已被格式化的Json
        function deleteExtFormPropertyEl(json) {
            for (var p in json) {
                var propertyName = p.toString();
                if (propertyName.indexOf("-inputEl") != -) {
                    json[propertyName.replace("-inputEl", "")] = json[p];
                    delete json[p];
                }
            }
            return json;
        }

//返回一个以逗号分隔的存储json属性名的字符串
        function getDirtyPropertyNames(json) {
            var propertyNames = "";
            for (var p in json) {
                propertyNames=propertyNames + p.toString() + ",";
            }
            return propertyNames.substring(, propertyNames.length-);
        }

//返回一个以逗号分隔的存储json属性值的字符串
        function getDirtyPropertyValues(json) {
            var propertyValues = "";
            for (var p in json) {                                                    
                propertyValues = propertyValues + json[p].toString() + ",";
            }
            return propertyValues.substring(, propertyValues.length - );
        }
                                            
        jsonDirty = deleteExtFormPropertyEl(jsonDirty);                                       
        var dirtyPropertyNames = getDirtyPropertyNames(jsonDirty); //将json数据的属性名转换成字符                                         
        var dirtyPropertyValues = getDirtyPropertyValues(jsonDirty); //将json数据的属性值转换成字符
                                            
        Ext.Ajax.request({
            method: "post",
            url: "/Personnel/EmployeeMsgReset",
            params: { ID: record.get("UserId"), dirtyPropertyNames: dirtyPropertyNames, dirtyPropertyValues: dirtyPropertyValues},
            success: function (r) {
                var m = Ext.decode(r.responseText);
                Ext.Msg.alert("", m.msg);
            },
            failure: function () { Ext.Msg.alert("", "操作失败"); }
        });
    }
},

提交表单时处理Json

[HttpPost]
public ContentResult EmployeeMsgReset( int ID, string dirtyPropertyNames ,string dirtyPropertyValues )
{            
    try
    {
        var user = DBContext.UserManagers.Single ( u => u.UserId == ID );
        Yin.PhantomPropertyValueReset ( user , dirtyPropertyNames , dirtyPropertyValues ); //根据表单提交的数据更新对应的属性值
        DBContext.Entry ( user ).State = System.Data.Entity.EntityState.Modified; //通知此实体的属性已被修改
        DBContext.SaveChanges ( );
        DBContext.Dispose ( );
    }
    catch
    {
        return Content ( "{msg:'操作失败'}" );
    }
    return Content ( "{msg:'操作成功'}");

服务端

文本框和按钮+图标 

//创建表单
Ext.create("Ext.form.Panel", {
    id: "formLogin",
    title:"Drugs ERP Login",
    renderTo: "loginBox",
    width: ,
    bodyPadding:,
    style: "padding:10px;",  //去除panel组件dom元素的边框
    border: false, // 去除panel组件的边框
    defaultType: "textfield",
    defaults:{style:"margin-top:10px;"},
    layout: {
        type: 'vbox',
        align: 'center'
    },
    items: [
            {
                height: ,
                emptyText:"用    户",
                fieldStyle: { background: '#ffffff url(/Img/Ico/user.png) no-repeat 8px center', paddingLeft: '33px' }
            },
            {
                height: ,
                emptyText: "密    码",
                fieldStyle: { background: '#ffffff url(/Img/Ico/block.png) no-repeat 8px center', paddingLeft: '33px' }
            },
            {
                xtype:"button",
                style: "border:none;background:#16699E;margin-top:10px;",
                iconCls:"btnIco",
                width: ,
                height:,
                frame:false,
                border: false,
                text:"登  入"
            }
    ]            
});
/*按钮文字*/
.x-btn-inner {
    font-family: Arial !important;
    color: white !important;
}

/*按钮a标签*/
.x-btn {
    text-decoration: none !important;
}

/*按钮内图标*/
.btnIco {
    background: url(../../Img/Ico/login.png);
    margin-left:78px;
}

Javascript - ExtJs - Ext.form.Panel组件

验证码组件扩展

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Web;
using System.Web.SessionState;

namespace WebErp.Ashx
{
    /// <summary>
    /// checkcode 的摘要说明
    /// </summary>
    public class ValidCode : IHttpHandler, IRequiresSessionState
    {
        HttpContext context;
        public void ProcessRequest( HttpContext context1 )
        {
            this.context = context1;
            CreateCheckCodeImage ( GenerateCheckCode ( ) );
        }

public bool IsReusable
        {
            get
            {
                return false;
            }
        }

private string GenerateCheckCode( )
        {
            int number;
            char code;
            string checkCode = String.Empty;

System.Random random = new Random ( );
            for ( int i =  ; i <  ; i++ )
            {
                number = random.Next ( );

if ( number %  ==  )
                    code = ( char ) ( '0' + ( char ) ( number %  ) );
                else
                    code = ( char ) ( 'A' + ( char ) ( number %  ) );

checkCode += code.ToString ( );
            }
            context.Session [ "chkcode" ] = checkCode;
            return checkCode;
        }

private void CreateCheckCodeImage( string checkCode )
        {
            if ( checkCode == null || checkCode.Trim ( ) == String.Empty )
                return;
            Bitmap image = new Bitmap ( ( int ) Math.Ceiling ( ( checkCode.Length * 20.5 ) ) ,  );
            Graphics g = Graphics.FromImage ( image );

try
            {
                //生成随机生成器
                Random random = new Random ( );

//清空图片背景色
                g.Clear ( Color.White );

//画图片的背景噪音线
                for ( int i =  ; i <  ; i++ )
                {
                    int x1 = random.Next ( image.Width );
                    int x2 = random.Next ( image.Width );
                    int y1 = random.Next ( image.Height );
                    int y2 = random.Next ( image.Height );

g.DrawLine ( new Pen ( Color.Silver ) , x1 , y1 , x2 , y2 );
                }

Font font = new System.Drawing.Font ( "Arial" ,  , ( System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic ) );
                System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush ( new Rectangle (  ,  , image.Width , image.Height ) , Color.Blue , Color.DarkRed , 1.2f , true );
                g.DrawString ( checkCode , font , brush ,  ,  );

//画图片的前景噪音点
                for ( int i =  ; i <  ; i++ )
                {
                    int x = random.Next ( image.Width );
                    int y = random.Next ( image.Height );

image.SetPixel ( x , y , Color.FromArgb ( random.Next ( ) ) );
                }

//画图片的边框线
                g.DrawRectangle ( new Pen ( Color.Silver ) ,  ,  , image.Width -  , image.Height -  );

System.IO.MemoryStream ms = new System.IO.MemoryStream ( );
                image.Save ( ms , System.Drawing.Imaging.ImageFormat.Gif );
                context.Response.ClearContent ( );
                context.Response.ContentType = "image/Gif";
                context.Response.BinaryWrite ( ms.ToArray ( ) );
            }
            finally
            {
                g.Dispose ( );
                image.Dispose ( );
            }
        }
    }
}

ashx

Ext.define('Ext.Yin.validcode', {

extend: 'Ext.form.field.Trigger',
    alias: ['widget.verifycodefield', 'widget.validcode'],
    // 图片的URL地址
    codeImgUrl: Ext.BLANK_IMAGE_URL,
    // 图片和输入框之间的距离
    imgMargin: ,
    // 图片的宽度
    imgWidth: ,
    // 图片的高度
    imgHeight: ,
    // 点击图片的时候是否清空输入框
    clearOnClick: true,
    // 临时的FieldBody样式
    extraFieldBodyCls: Ext.baseCSSPrefix + 'form-file-wrap',
    componentLayout: 'triggerfield',
    childEls: ['imageWrap'],

initComponent: function () {
        var self = this;
        Ext.apply(self, {
            allowBlank: self.allowBlank,
            blankText: self.blankText
        });
        self.callParent();
    },

onRender: function () {
        var me = this, id = me.id, inputEl;

me.callParent(arguments);

inputEl = me.inputEl;

// name goes on the fileInput, not the text input
        inputEl.dom.name = '';

// 将imgConfig对象拷贝给前一个参数,并覆盖
        me.image = new Ext.Img(Ext.apply({
            renderTo: id + '-imageWrap',
            ownerCt: me,
            ownerLayout: me.componentLayout,
            id: id + '-img',
            ui: me.ui,
            src: me.codeImgUrl,
            disabled: me.disabled,
            width: me.imgWidth,
            height: me.imgHeight,            
            style: me.getImgMarginProp() + me.imgMargin + 'px;cursor:pointer;',
            inputName: me.getName(),
            listeners: {
                scope: me,
                click: {
                    element: 'el',
                    fn: me.onImgClick
                }
            }
        }, me.imgConfig));

// me.browseButtonWrap.dom.style.width =
        // (me.browseButtonWrap.dom.lastChild.offsetWidth +
        // me.button.getEl().getMargin('lr')) + 'px';

me.imageWrap.dom.style.width = (me.imgWidth + me.image.getEl()
                .getMargin('lr'))
                + 'px';
        if (Ext.isIE) {
            me.image.getEl().repaint();
        }
    },
    //将文本框描红
    listeners:{
        blur: function () {
            var el = this.inputEl;
            var val = this.inputEl.dom.value;
            if (val.trim() == "") {
                this.setFieldStyle("border:1px solid #CF4C35;");                
            }
            else {                
                this.setFieldStyle("border:1px solid #D9D9D9;");
            }
        }
    },
    /**
     * Gets the markup to be inserted into the subTplMarkup.
     */
    getTriggerMarkup: function () {
        return '<td id="' + this.id + '-imageWrap"></td>';
    },

onImgClick: function () {
        // 重新定义图片地址
        this.image.setSrc(this.codeImgUrl + '?time=' + new Date().getTime());
        this.reset();
    },
    getImgMarginProp: function () {
        return 'margin-left:';
    },

setValue: Ext.emptyFn,

reset: function () {
        var me = this, clear = me.clearOnClick;
        if (me.rendered) {
            if (clear) {
                me.inputEl.dom.value = '';
            }
        }
    }

});

Ext.Yin.validcode

{
    xtype: "validcode",
    width: ,
    id: 'validImg',
    emptyText:"验证码",
    allowBlank: false,
    blankText:"no text",
    formID:"formLogin",
    codeImgUrl: '/Ashx/ValidCode.ashx?d' + new Date().getMilliseconds()       //从服务端返回的验证码程序                
}

render

动态设置字段的值

msg = "<div style='color:red;'>sam</div>";
Ext.getCmp("userName").setValue(msg);//支持为字段的值包裹html代码

表单布局

表单面板默认一个子组件占满一行,如果要使多个子组件在一行显示,须在某个容器类型的组件中配置其layout为column,这表示声明了当前组件的items子组件都会按照列与列的并排效果予以显示。子组件使用columnWidth声明它在父容器组件里所占的宽度,取值是百分比。(.10表示10%),假设两个组件并排显示只需要将它们的columnWidth设为.50即可,这样它们就会各占父容器组件的一半。容器组件是什么?container、fieldset等都是属于容器。推荐使用fieldset作子组件的容器,经测试,fieldset更容易布局。如果不使用fieldset而是使用container,那么各种框前的文本的宽度(labelWidth)非常不易控制(框前的文本和框距离很长),并且不使用fieldset,那么formPanel会默认给父容器组件加上很粗很丑的边框线,用border:false还祛除不了。

Ext.onReady(function () {

Ext.create("Ext.form.Panel", {
        id: "employeeEntryForm",
        renderTo: "employeeEntry",
        title: '员工入职登记',
        border:false,
        frame:false,
        style: "padding:10px;",          
        items: [
            {
                layout: "column",//声明当前组件的子组件将并排显示      
                border: false,
                style: "margin-top:10px;",
                items: [
                    {
                        //并排的子组件
                        xtype: "fieldset",
                        title: "信息",
                        columnWidth: .49,         //占49%                   
                        style: "padding:5px;margin-left:10px;",
                        defaultType: "textfield",
                        fieldDefaults: {
                            labelWidth: ,
                            labelAlign: "left"
                        },
                        items: [
                            { fieldLabel: "用  户" },
                            { fieldLabel: "真实姓名" },
                            { fieldLabel: "生  日" },
                            { fieldLabel: "手机号" },
                            { fieldLabel: "Email地址" },
                            { fieldLabel: "家庭住址" }                                
                        ]
                    },
                    {
                        //并排的子组件
                        xtype: "fieldset",
                        title: "企业",
                        columnWidth: .50,  //占50%             
                        style: "margin-left:10px;padding:5px;",
                        defaultType: "textfield",
                        fieldDefaults: {
                            labelWidth: ,
                            labelAlign: "left"
                        },
                        items: [
                            { fieldLabel: "所属部门", xtype: 'combobox', id: 'departmentID', displayField: 'key', valueField: 'value', emptyText: "------选择------", blankText: "没有选择部门", editable: false, hiddenName: "departmentID", mode: "remote", store:"departmentStore"},
                            { fieldLabel: "角色" },                                
                            { fieldLabel: "照  片" },
                            { fieldLabel: "性  别" },
                            { fieldLabel: "在  职" },
                            { fieldLabel: "排  序" }
                        ]
                    }
                ]
            }
        ],
        buttons: [
                { text: '提交', style: "margin-top:20px", handler: function () { Ext.MessageBox.alert("", "提交成功"); } },
                { text: "取消", style: "margin-top:20px", handler: function () { Ext.getCmp().getForm("employeeEntryForm").reset(); } }
        ]
    });

});

列布局

去掉formPanel的border和frame后:

Javascript - ExtJs - Ext.form.Panel组件

Ext.create("Ext,form.Panel", {
    renderTo: "box",
    title: '注册',
    width: ,
    style: "padding:10px;",
    frame: true,
    items: [
        {
            //fieldset独占一行
            xtype: "fieldset",
            layout: "column",//声明当前组件的子组件将并排显示
            title: "第一行",
            defaultType: "textfield",
            style: "padding:10px;",
            width: ,
            fieldDefaults: {
                labelWidth: ,
                labelAlign: "left"
            },
            items: [
                { fieldLabel: "用  户" },
                { fieldLabel: "注册时间", labelWidth: , style: "margin:0 15px 0 15px;" },
                { fieldLabel: "Email" }
            ]
        },
        {
            //fieldset独占一行
            xtype: "fieldset",
            layout: "column",//声明当前组件的子组件将并排显示
            title: "第二行",
            defaultType: "textfield",
            style: "padding:10px;",
            width: ,
            fieldDefaults: {
                labelWidth: ,
                labelAlign: "left"
            },
            items: [
                { fieldLabel: "企业用户" },
                { fieldLabel: "通信地址", labelWidth: , style: "margin:0 15px 0 15px;" },
                { fieldLabel: "公司地址" }
            ]
        },
    ],
    buttons: [
            { text: '提交', style: "margin-top:20px", handler: function () { Ext.MessageBox.alert("", "提交成功"); } },
            { text: "取消", style: "margin-top:20px", handler: function () { Ext.MessageBox.alert("", "取消成功"); } }
    ]
});

列布局

Javascript - 学习总目录

上一篇:linux内核分析第二周


下一篇:Linux内核分析第二周--操作系统是如何工作的