extjs5 filefield之triggers使用

概要

最近项目有个需求,动态生成的表单中上传图片,但是因为一些特殊原因,表单无法直接提交,需要将表单中的数据特殊处理,然后以ajax方式提交。

此外,图片上传后还需要回显,并将上传后的文件名同样以ajax提交。真是需求搞死人:(

解决思路

1.看到extjs文档中表单的field都有个triggers属性,可以使用triggers来控制文件的上传

2.将返回的文件名,set到一个hidden控件中

3.使用displayfield来回显图片,具体的做法就是在value属性添加image属性

4.图片可以删除,这个单独通过事件样式来控制

注:extjs有个xtype:image类型,但是图片加载速度太慢,直接放弃

实现过程

主要的代码

var form = Ext.create('Ext.form.FormPanel', {
	height : 500,
	width : 400,
	items : [{
		xtype : 'filefield',        
        fieldLabel : '图片',
		buttonText : '选择..',
		// listeners : {
		// 	render : function(that) {
		// 		var domId = that.triggers.bar.domId;
		// 		Ext.get(domId).addListener('click', function() {
		//         /*此处解决triggers中handler无效的问题,如果无效只需要将bar中handler代码写在此处*/	
		// 		})
		// 	}
		// },
		triggers : {
			bar : {
				handler : function() {
					var that = this;
					var file = that.fileInputEl.dom.files[0];
					if(!file) {
						Ext.Msg.show({
							title : '提示',
							msg : '请选择图片',
							buttons : Ext.Msg.OK,
							icon : Ext.Msg.WARNING
						})
						return false;
					}
					var formData = new FormData();
					formData.append('multipartFile', file);
					
					var oReq = new XMLHttpRequest();
					oReq.open("POST", Global.basePath + 'dataMain/upload.htm');
					oReq.onreadystatechange = function() {
						if(oReq.readyState == 4) {
							if(oReq.status == 200) {
								var data = Ext.decode(oReq.responseText);
								if(data.success) {
									// 文件名
									var fileName = data.message;
									// 存储文件名
									var hiddenCt = Ext.getCmp('hidden');
									hiddenCt._value.push(data.message)
									hiddenCt.setValue(hiddenCt._value.join(','))
									
									// 回显图片
									var displayfieldCt = Ext.getCmp('displayfield');
									var displayValue = displayCt.getValue();
									displayValue += '<span class="displayfield-span"><img class="displayfield-img" src="' + Global.basePath + 'dataMain/download.htm?fileName=' + fileName + '"/><span  _fileName="' + fileName + '" class="displayfield-close"></span></span>';
									displayCt.setValue(displayValue);
								} else {
									Ext.Msg.show({
										title : '提示',
										msg : data.message,
										buttons : Ext.Msg.OK,
										icon : Ext.Msg.ERROR
									})
								}
							} else {
								console.log(oReq.responseText);
								Ext.Msg.show({
									title : '提示',
									msg : '上传失败',
									buttons : Ext.Msg.OK,
									icon : Ext.Msg.WARNING
								})
							}
						}
					}
					oReq.send(formData);
				}
			}
		}
	}, {
		xtype : 'hidden',
		id : 'hidden',
		_value : []	  // 自定义的属性,存储上传图片的文件名
	}, {
		xtype : 'displayfield',
		id : 'displayfield',
		value : '',
		fieldLabel : '.',
		labelStyle : 'color:white'  // 让fieldLabel'不显示',实际上是显示的,所以没有使用hideLabel属性
	}],
	listeners : {
		afterrender : function(that){
            // 删除图片进行事件绑定
			var closeDoms = Ext.query('.displayfield-close');
			for(var i = 0, len = closeDoms.length; i < len; i++) {
				Ext.get(closeDoms[i]).addListener('click', function() {
					var dom = this.dom;
						hiddenCt = Ext.getCmp('hidden'),
						displayfieldCt = Ext.getCmp('displayfield'),
						_value = hiddenCt._value,
						displayfieldDom = dom.parentNode.parentNode;  // 先将顶级dom保存下来,不然待会dom.parentNode删除后就无法查询该顶级dom

					Ext.Array.remove(_value, dom.getAttribute("_fileName"));
					hiddenCt.setValue(_value.join(","));
					Ext.get(dom.parentNode).remove();
					// 处理displayfield的value
					displayfieldCt.setValue(Ext.get(displayfieldDom).getHtml());
				})
			}
		}
	}
})    

css样式

.displayfield-img {
  width:100px;
  height:100px;
  margin:13px 13px 0 0;
  border:1px solid #CCC;
}

.displayfield-span {
  position: relative;
  margin-right: 5px;
}

.displayfield-close {
  position: absolute;
  right: 0;
  overflow: hidden;
    width: 16px;
    height: 16px;
    background-image: url(ext/images/tools/tool-sprites.png);
    background-position: 0 0;
    margin: 0;
    filter: alpha(opacity=100);
    opacity: 1;
}

.displayfield-close:hover {
  opacity: .6;
}

问题解决

1.图片删除后,再次上传图片,之前的图片会再次显现出来,原因是display的value没有更新,所以使用displayfieldCt.setValue(Ext.get(displayfieldDom).getHtml())手动刷新displayfield

2.图片的删除之事件绑定,需要form初始化之后绑定,可以使用afterrender,afterlayout等事件绑定

3.filefield的triggers的handler可能会无效果,所以需要再filefield的listeners中手动绑定事件

4.Ext.get方法会把dom对象转为Ext.dom.Element对象

效果图

上传之前

上传之后

删除图片

 

 总结

1.使用了filefield的triggers属性,但是可能无效果,需要手动处理下绑定事件

2.使用了FormData结合Ajax上传文件,解决了纯Ajax无法上传文件的历史问题,但是IE10以上,Chrome28+,FireFox23+等现代浏览器才支持,不适宜老古董:)

3.使用displayfield来显示图片,但要手动刷新value

4.xtype:image显示图片速度过慢,放弃使用,改用displayfield的value配合html来显示图片

5.最终考虑兼容性的问题,并未按照此种写法满足项目需求,而是使用xtyep:fieldcontainer嵌套xtype:form来上传文件

6.使用了ext很多很少用的组件和技术,但是会进一步熟练extjs.

 

posted @ 2016-02-19 17:01  贝拉巴拉  阅读(1712)  评论(0)    收藏  举报