利用ExtJs的Anchor可以为ExtJs自带的表单Form各个组件进行布局,当然,使用《【ExtJs】带日期组件的文本输入框、容器与Ext.Msg.alert告警框告警两次》(点击打开链接)中的vbox也是可以的。其实ExtJs的表单插件与表单布局并不是关键,ExtJs的表单验证还好,就几行语句就能够完成。关键是ExtJs的表单提交必须通过Ajax方式,而在后台必须传回一个Json完成表单的提交,可能有点复杂,下面就以php作为ExtJs的后台处理来说明问题ExtJs的表单。aspx,jsp等各位只要改好参数获取语句一样可以的。


一、基本目标

如下图,这是在Windows2003自带的纯种IE6浏览器执行的效果,首先在浏览器中有一个按钮,点击之后可以打开表单窗口,用户填写的信息必须符合要求,如果没有通过验证,表单的“确定”按钮是灰色状态,当然,点击“关闭”按钮能够随时关闭这个对话框的。

这里面有文本框、密码框、复选框、下拉列表、单选框,所有的值都能够传到后台的formSubmit.php处理之后,再传回来前台。这里不推荐使用ExtJs的颜色组件,因为所有不兼容IE6的插件都是骗人的坏人!



二、基本思想

整个表单的布局如下图,皆是纯粹的ExtJs表单组件,没有用到HTML来布置。


而Login.html这个页面的HTML布局仅仅是一个带id=btn1的按钮,其余所有布局皆由JavaScript脚本完成。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Ext表单</title>
        <script type="text/javascript" src="js/ext-all.js"></script>
        <script type="text/javascript" src="js/bootstrap.js"></script>
        <script type="text/javascript" src="js/ext-lang-zh_CN.js"></script>
        <link href="ext-theme-classic/ext-theme-classic-all.css" rel="stylesheet" type="text/css">
    </head>
    <body>
    	<button id="btn1" type="button">打开表单</button>
    </body>
</html>

三、核心脚本

1、Login.html

这个前端页面不含有任何的后端语言

(1)首先可以声明一个名为window1的window,里面的就放一个名为form1的form,指明btn1的onclick事件为显示window1。这部分与《【ExtJs】折叠式布局与卡片式布局》(点击打开链接)一模一样。不再赘述了。

		var window1=Ext.create('Ext.window.Window', {
			renderTo: Ext.getBody(),
			header: false,
            border: false, //没有边框
			resizable: false, //不可以自由调整大小,默认可以
            width: 400,
			items:[form1]
		});
        window1.show();
(2)之后再声明表单使用ExtJs未能通过验证的错误消息,如果没有这两行,ExtJs对于未能通过验证的表单,不会有任何错误的提醒。

        Ext.QuickTips.init();
        Ext.form.Field.prototype.msgTarget = 'side';
(3)其后是真正的核心,ExtJs的表单

        var form1 = Ext.create('Ext.form.Panel', {
            width: 400,
            method: 'POST',
            layout: 'anchor',
            title: 'Ext表单',
            items: [{
                fieldLabel: '用户名',
                xtype: 'textfield',
                name: 'username',
                regex: /^[A-Za-z]{4,12}$/,//正则表达式
                regexText: '必须4-12个英文字符',
                anchor: '90%'
            }, {
                fieldLabel: '密码',
                xtype: 'textfield',
                inputType: 'password',//密码
                name: 'password',
                regex: /^[A-Za-z]{4,12}$/,//正则表达式
                regexText: '必须4-12个英文字符',
                anchor: '90%'
            }, {
                fieldLabel: '复选选框',
                xtype: 'checkboxgroup',
                items: [{
                    boxLabel: '选项1',
                    name: 'c1'
                }, {
                    boxLabel: '选项2',
                    name: 'c2',
					checked: true
                }]
            }, {
                fieldLabel: '下拉列表',
                xtype: 'combobox',
                layout: 'hbox',
                querymode: 'local',
                valueField: 'id',//列表value值使用store中的id字段
                displayField: 'name',//显示值使用store中的name字段
                forceSelection: true,//不得自由输入,不得为空,必须从下拉列表中选择一项
				name:'combobox',
                allowBlank: false,
                store: {
                    fields: ['id', 'name'],
                    data: [{
                        'id': 'c1',
                        name: 'c1'
                    }, {
                        'id': 'c2',
                        name: 'c2'
                    }, {
                        'id': 'c3',
                        name: 'c3'
                    }]
                }
            }, {
                fieldLabel: '单选框',
                xtype: 'radiogroup',
                allowBlank: false,
                items: [{
                    boxLabel: '选项1',
                    name: 'radiobox',
                    inputValue: 'r1'
                }, {
                    boxLabel: '选项2',
                    name: 'radiobox',
                    inputValue: 'r2'
                }, {
                    boxLabel: '选项3',
                    name: 'radiobox',
                    inputValue: 'r3'
                }]
            }],
            bbar: [{
                xtype: 'tbfill'
            }, {
                xtype: 'button',
                text: '确定',
                disabled: true,
                formBind: true,
                listeners: {
                    click: function(){
                        var thisForm = form1.getForm();
                        thisForm.submit({
                            url: "formSubmit.php",
                            success: function(form, action){
                                Ext.Msg.alert('Success', action.result.msg, function(){
                                   window1.hide();
                                });
                            }
                        });
                    }
                }
            }, {
                xtype: 'button',
                text: '关闭',
                listeners: {
                    click: function(){
                       window1.hide();                               
                    }
                }				
            }, {
                xtype: 'tbfill'
            }]
        });
声明这个表单的宽度、提交方式、布局为anchor、标题等基本信息之后,关键是items中的内容,这里面就是ExtJs的一个又一个表单组件。

先是基本的输入框,其类型是textfield,name的设置是为了一会儿后端页面formSubmit.php获取时使用。其中regex则是验证的正则表达式,regexText就是未能通过认证时候提示的错误信息。anchor:'90%'指明这个表单占整行的90%。

随后密码框的设置,其类型同样是textfield,但要多补一个inputType: 'password',指明这个输入框为密码框。

复选选框xtype: 'checkboxgroup'与单选组xtype: 'radiogroup',没什么好说,对于单选组,记得补上一个allowBlank: false,禁止未空就可以了。

关键是下拉列表,也就是原来的<select>标签,最为复杂,这东西ExtJs默认是能让用户自由输入的,然后选项都是从后端读取的,十分高端,现在能够改到是一个普通的下拉列表,必须从里面选择一个元素,这才符合我们的思维。

最后在底部的工具栏设置左右占位符与两个按钮,这个bbar在《【ExtJs】tabPanel标签页与修改标签页的内容》(点击打开链接)已经说过了,关键是两个按钮的onclick事件,先说简单的“关闭”按钮,这个按钮必须设置window1是隐藏,不要用close()方法,这个关闭是连这个window1变量的都销毁了,再也打不开了,所以只能是隐藏。最重要的是提交按钮,首先要获取form1这个表单,然后指明其提交之后的属性,action.result.msg是接受,后端在你验证成功之后的信息。这里只写了一种情况,其实还有一个Failure的情况,完整的写法是这样的:

                listeners: {
                    click: function(){
                        var thisForm = form1.getForm();
                        thisForm.submit({
                            url: "formSubmit.php",
                            success: function(form, action){
                                //成功之后怎么怎么样
                                },
			    failure: function(form, action){
				//失败之后怎么怎么样
                                });                   
                        }
                    }
                }	

其成功与否是根据formSubmit.php这个后端网页,最终打印出来的字符串所决定的,这个字符串就是一个json

如果是这样的json,则表示这个表单提交成功,其传回值为ss的消息给前端

{
"success":true,
"msg":"ss"
}
如果把success的值从true改成failure,则表示这个表单提交失败,同样传回值为ss的消息给前端。

然后表单提交之后,通过弹窗的callback函数完成弹窗其关闭表单窗口动作,这个在《【ExtJs】带日期组件的文本输入框、容器与Ext.Msg.alert告警框告警两次》(点击打开链接)也讲过了。

综上所述,整个Login.html的代码如下,注意刚刚提到的任何代码都要写在Ext.onReady(function(){});的{}里面,这个从《【ExtJs】ExtJs4.2.1的配置与Helloworld》(点击打开链接)开始就已经多次提及。

同时注意你属性与属性之间的声明的逗号,不要以逗号完成json的结尾,否则IE系列无法识别,这在《【JavaScript】数组定义末尾请不要留下逗号》(点击打开链接)已经说过了。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Ext表单</title>
        <script type="text/javascript" src="js/ext-all.js"></script>
        <script type="text/javascript" src="js/bootstrap.js"></script>
        <script type="text/javascript" src="js/ext-lang-zh_CN.js"></script>
        <link href="ext-theme-classic/ext-theme-classic-all.css" rel="stylesheet" type="text/css">
    </head>
    <body>
    	<button id="btn1" type="button">打开表单</button>
    </body>
</html>
<script>
    Ext.onReady(function(){
        Ext.QuickTips.init();
        Ext.form.Field.prototype.msgTarget = 'side';
        //以上这两行代码,声明表单错误验证的信息
        var form1 = Ext.create('Ext.form.Panel', {
            width: 400,
            method: 'POST',
            layout: 'anchor',
            title: 'Ext表单',
            items: [{
                fieldLabel: '用户名',
                xtype: 'textfield',
                name: 'username',
                regex: /^[A-Za-z]{4,12}$/,//正则表达式
                regexText: '必须4-12个英文字符',
                anchor: '90%'
            }, {
                fieldLabel: '密码',
                xtype: 'textfield',
                inputType: 'password',//密码
                name: 'password',
                regex: /^[A-Za-z]{4,12}$/,//正则表达式
                regexText: '必须4-12个英文字符',
                anchor: '90%'
            }, {
                fieldLabel: '复选选框',
                xtype: 'checkboxgroup',
                items: [{
                    boxLabel: '选项1',
                    name: 'c1'
                }, {
                    boxLabel: '选项2',
                    name: 'c2',
					checked: true
                }]
            }, {
                fieldLabel: '下拉列表',
                xtype: 'combobox',
                layout: 'hbox',
                querymode: 'local',
                valueField: 'id',//列表value值使用store中的id字段
                displayField: 'name',//显示值使用store中的name字段
                forceSelection: true,//不得自由输入,不得为空,必须从下拉列表中选择一项
				name:'combobox',
                allowBlank: false,
                store: {
                    fields: ['id', 'name'],
                    data: [{
                        'id': 'c1',
                        name: 'c1'
                    }, {
                        'id': 'c2',
                        name: 'c2'
                    }, {
                        'id': 'c3',
                        name: 'c3'
                    }]
                }
            }, {
                fieldLabel: '单选框',
                xtype: 'radiogroup',
                allowBlank: false,
                items: [{
                    boxLabel: '选项1',
                    name: 'radiobox',
                    inputValue: 'r1'
                }, {
                    boxLabel: '选项2',
                    name: 'radiobox',
                    inputValue: 'r2'
                }, {
                    boxLabel: '选项3',
                    name: 'radiobox',
                    inputValue: 'r3'
                }]
            }],
            bbar: [{
                xtype: 'tbfill'
            }, {
                xtype: 'button',
                text: '确定',
                disabled: true,
                formBind: true,
                listeners: {
                    click: function(){
                        var thisForm = form1.getForm();
                        thisForm.submit({
                            url: "formSubmit.php",
                            success: function(form, action){
                                Ext.Msg.alert('Success', action.result.msg, function(){
                                   window1.hide();
                                });
                            },
							failure: function(form, action){
                                Ext.Msg.alert('Failure', action.result.msg, function(){
                                   window1.hide();
                                });
                            }
                        });
                    }
                }
            }, {
                xtype: 'button',
                text: '关闭',
                listeners: {
                    click: function(){
                       window1.hide();                               
                    }
                }				
            }, {
                xtype: 'tbfill'
            }]
        });
		var window1=Ext.create('Ext.window.Window', {
			renderTo: Ext.getBody(),
			header: false, //没有标题
            border: false, //没有边框
			resizable: false, //不可以自由调整大小,默认可以
            width: 400,
			items:[form1]
		});
		window1.show();
     	Ext.get("btn1").on("click", function(){
            window1.show();
        });  
    });
 
</script>


2、formSubmit.php

因此后端处理页面也就可以这样写了,当然这里没有设置错误的情况,只是获取前端,各个表单组件传过来的值,然后放到msg里面而已。

唯一值得注意的是对复选框的处理,如果前端复选框没有选,它传过来的值就为空,这里必须处理一下,否则一会打印出来的json字符串中的msg部分是不正常的,Login.html这个页面一直等不到想要的Json字符串,会一直处于无法响应的状态。使用Jsp与Aspx的朋友同样要面对这个问题,估计可能会出现空指针什么的。

<?php
$username=$_REQUEST["username"];
$password=$_REQUEST["password"];
if(empty($_REQUEST["c1"])){
	$c1="off";
}
else{
	$c1=$_REQUEST["c1"];
}
if(empty($_REQUEST["c2"])){
	$c2="off";
}
else{
	$c2=$_REQUEST["c2"];
}
$combobox=$_REQUEST["combobox"];
$radiobox=$_REQUEST["radiobox"];
echo "{
'success':true,
'msg':'传过来的用户名:{$username}<br>密码:{$password}<br>复选框的值:{$c1},{$c2}<br>下拉列表的值:{$combobox}<br>单选框的值:{$radiobox}'
}";
?>


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐