×
文章路径: WEB前端 > JS

页面checkbox向后台传值需注意的一个细节

发表于11个月前(Mar 17, 2017 8:26:58 PM)  阅读 449  评论 0

分类: WEB前端 JS

标签: checkbox ajax serialize serializeArray

checkbox是很常用的一个html控件,在使用时有一个细节需要注意,如果你的checkbox没有被选中,那么这个name属性将不会随表单一起提交,当然,笔者说的是serialize表单ajax提交的方式(至于页面默认同步的提交方式,笔者好像工作以来基本都没用过,都是采用ajax异步提交的,使用页面默认同步的方式,会不会有该问题,笔者未做验证)。举个例子:

<form id="form">
    <input type="checkbox" name="football"/>
</form>

当你勾选了该checkbox时,提交表单会带参数football=on,如果没有勾选,提交的表单就没有football这个参数。平时,我们基本上可以根据没有football这个参数就认为用户没有勾选该项,这完全没有问题。但笔者在做基础平台时,做通用功能的时候,如果每个checkbox参数这样去判断一次,感觉会很累赘,无法利用SpringMVC的自动参数转换,所以,笔者在想为什么checkbox不在没有勾选的时候传个off进来呢。

于是笔者打开了jquery的源码(2.1.4版本),找到如下代码段:

var rcheckableType = (/^(?:checkbox|radio)$/i);

jQuery.fn.extend({
	serialize: function() {
		return jQuery.param( this.serializeArray() );
	},
	serializeArray: function() {
		return this.map(function() {
			// Can add propHook for "elements" to filter or add form elements
			var elements = jQuery.prop( this, "elements" );
			return elements ? jQuery.makeArray( elements ) : this;
		})
		.filter(function() {
			var type = this.type;

			// Use .is( ":disabled" ) so that fieldset[disabled] works
			return this.name && !jQuery( this ).is( ":disabled" ) &&
				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
				( this.checked || !rcheckableType.test( type ) );
		})
		.map(function( i, elem ) {
			var val = jQuery( this ).val();

			return val == null ?
				null :
				jQuery.isArray( val ) ?
					jQuery.map( val, function( val ) {
						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
					}) :
					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
		}).get();
	}
});

在serializeArray方法里面,( this.checked || !rcheckableType.test( type ) )这句代码决定了只有checked的checkbox,radio才会提交,这段代码有点拗口,仔细理理。

找到了原因,解决起来就好办了,笔者采用的方法是,在保留原来代码用意的同时稍微进行一下扩展,笔者作了如下设定,如果checkbox包含了alwaysSubmit这样一个class样式,就不管该checkbox有没有选中,都进行提交,具体代码如下,该代码可以放置在jquery加载完毕后的任意地方执行,以覆盖原来的全局方法。

var r20 = /%20/g,
rbracket = /\[\]$/,
rCRLF = /\r?\n/g,
rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
rsubmittable = /^(?:input|select|textarea|keygen)/i;
var rcheckableType = ( /^(?:checkbox|radio)$/i );

$.fn.extend( {
	serialize: function() {
		return jQuery.param( this.serializeArray() );
	},
	serializeArray: function() {
		return this.map( function() {
			// Can add propHook for "elements" to filter or add form elements
			var elements = jQuery.prop( this, "elements" );
			return elements ? jQuery.makeArray( elements ) : this;
		} )
		.filter( function() {
			var type = this.type;
			// Use .is( ":disabled" ) so that fieldset[disabled] works
			return this.name && !jQuery( this ).is( ":disabled" ) &&
				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
				((rcheckableType.test( type ) && jQuery( this ).hasClass("alwaysSubmit")) ||( this.checked || !rcheckableType.test( type ) ));
		} )
		.map( function( i, elem ) {
			var val = jQuery( this ).val();
			var type = this.type;
			if(rcheckableType.test( type ) && jQuery( this ).hasClass("alwaysSubmit")) {
				if(this.checked) {
					val = "on";
				} else {
					val = "off";
				}
			}
			return val == null ?
				null :
				jQuery.isArray( val ) ?
					jQuery.map( val, function( val ) {
						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
					} ) :
					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
		} ).get();
	}
});

可以看到,笔者在filter和map方法里面对包含alwaysSubmit class的checkbox、radio都作了特殊处理,这样,如果后台有个Boolean属性的值,将会直接转换为false。

发表评论