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.

浙公网安备 33010602011771号