页面中的扩展属性
扩展属性是相对页面的基本信息而言的,在部分页面中(尤其是进销存页面)设置扩展属性这一功能可以使得系统用户方便的进行个性化信息数据的生成和检索处理等。
据原系统中所具有的系统进行二次开发。
本文档将主要以采购申请单据为例。
首先,如果在采购申请这张单据中有添加扩展属性功能的需求的话,则需要在其业务单据页面上做以下动作:
1. 在采购申请单据的aspx页面中引用扩展属性的用户控件,页面代码如下:
2. 把扩展属性用户控件放在本单据中相应的位置(如图示2,具体可以根据实际页面来放置控件);
图示2
另外,需要在JS中作如下的动作:
1. 在页面加载所调用的方法DocumentReady()中需要调用这样一个方法GetExtAttr(TableName, null),这个方法中的第一个参数是当前业务单据在数据库中存储数据所对应的表名,如采购申请单据此参数为TableName = "officedba.PurchaseApply",第二个参数在之后会有所介绍。那么这个方法是怎么定义的呢?在什么位置对他进行定义呢?这些问题在之后的阐述中会一一解答。
2. 如果是从列表页面操作数据过来的话,也要在当前页面LOAD数据的JS方法中调用这样一个方法GetExtAttr(TableName, json.PurchaseApplyPrimary),这个方法中参数的意义和上述是一模一样的。
现在,来对上面提出的一些问题做解答。首先要了解扩展属性控件的页面的结构,如下图所示:
图示3
可以看到在这个控件中只是简单的填写了Panel容器控件以及一个隐藏域。马上将会阐述这样一个结构具体会有什么样的用途。
且看,控件中JS代码部分,首先来解释一下GetExtAttr(TableName, data)方法中代码。
var strKey = ''; //使用字段集合
function GetExtAttr(TableName, data) {
document.getElementById('GetExtAttributeControlNew_hiddKey').value = '';
var ExtTab = '';
Ext.Ajax.request({
method: "POST", //用POST方式传输
url: "http://www.cnblogs.com/../Handler/Office/SupplyChain/TableExtFieldsInfo.ashx", //目标地址
async: false,
params: 'action=all&TableName=' + TableName,
success: function(result) {
//数据获取完毕,填充页面据显示
//存在扩展属性显示页面扩展属性表格
var fun = new Function("return" + result.responseText);
var msg = fun();
if (parseInt(msg.totalCount) > 0) {
Ext.getCmp("GetExtAttributeControlNew_ExtPanel").show();
ExtTab = new Ext.Panel({
renderTo: 'GetExtAttributeControlNew_ExtPanel',
id: 'ExtTab',
layout: 'column',
border: true,
autoWidth: true,
items: GetExtAttrItems(msg.data)
});
}
document.getElementById("GetExtAttributeControlNew_hiddKey").value = strKey;
/******从列表页面到编辑页面获取扩展属性值**********************/
try {
if (data != null) {
ExtAttControl_FillValue(data);
}
} catch (e) { }
},
failure: function() {
Ext.Msg.alert("提示", "请求发生错误");
}
});
}
GetExtAttr(TableName, data)方法就是在当前业务单据中被调用的,这个方法中的主要功能是在业务单据页面上初始化扩展属性的展示。在上述所见代码中是经过了一次请求之后获取到扩展属性相关信息数据(数据包括扩展属性自定义项字段的名称、控件类型标记、索引以及扩展属性自定义项的个数等信息),通过所获取的这部分数据来对扩展属性的页面展示进行初始化;初始化的一个比较重要的代码块用红色位子坐了标记,这个代码块新建一个Panel容器来装载扩展属性信息数据,把这个Panel渲染到ExtPanel(见图示3,对这个Panel有定义) 中,另外比较重要的也是比较难于理解的是在items这个对象的赋值,本方法中是通过GetExtAttrItems(msg.data)来返回其所需数据,下面是这个方法的代码:
function GetExtAttrItems(items) {
var ControlID = ''; //控件id
var Control = null; //单个TextField控件的代码存放在这个对象中
var Cell = null; //一下将其初始化为一个TextField控件对象
//定义一个数组,用来作为返回的数据集合,数组中元素是一个个Control对象
var itemCollection = new Array();
for (var i = 0; i < items.length; i++) {循环对Control对象赋值
var item = items[i];
Control = new Object();
strKey += "|" + "ExtField" + item.EFIndex; //使用字段集合
ControlID = "ExtField" + item.EFIndex; //控件id
//通过EFType确定需要生成扩展属性自定义项的控件类型(1为TextField,2为ComboBox)
if (item.EFType == "1") {
//可以对比业务单据中列布局来理解以下代码
Control.columnWidth = 0.33;
Control.labelWidth = 70;
Control.layout = 'form';
Control.items = new Array();
Cell = new Ext.form.TextField({
xtype: 'textfield',
anchor: '84%',
id: ControlID,
labelCls: 'fieldlabel',
fieldLabel: item.EFDesc
});
Control.items.push(Cell);
} else if (item.EFType == "2") {
Control.columnWidth = 0.33;
Control.labelWidth = 70;
Control.layout = 'form';
Control.items = new Array();
var itemvalues = item.EFValueList.split('|');
var values = new Array();
for (var k = 0; k < itemvalues.length; k++) {
values.push([itemvalues[k], itemvalues[k]]);
}
Cell = new Ext.form.ComboBox({
xtype: 'combo',
anchor: '84%',
id: ControlID,
editable: false,
labelCls: 'fieldlabel',
fieldLabel: item.EFDesc,
triggerAction: 'all',
selectOnFocus:true,
mode: 'local',
forceSelection: true,
store: new Ext.data.ArrayStore({
id: 0,
fields: ['itemkey', 'itemname'],
data: values
}),
valueField: 'itemkey',
displayField: 'itemname'
});
Cell.insertItem(0, "--请选择--", "-1");
Cell.selectByIndex(0, true);
Control.items.push(Cell);
}
itemCollection.push(Control);
Control = null;
panel2 = null;
}
return itemCollection;
}
通过代码中的注释基本可以理解这段代码的意思;这段代码主要是通过循环的方法对各扩展属性生成控件对象后返回到上述的ExtTab中,之后就在页面中生成了我们所见到的效果。如下图示:
图示4
另外,就是对扩展属性赋值的一个操作。对扩展属性个自定义项赋值需要调用这个方法ExtAttControl_FillValue(data),其定义的代码如下:
//修改页面初始化扩展属性值
function ExtAttControl_FillValue(data) {
var strKey = document.getElementById("GetExtAttributeControlNew_hiddKey").value; //扩展属性字段值
var arrKey = strKey.split('|');
if (data.length > 0) {
for (var i = 0; i < data.length; i++) {
for (var t = 0; t < arrKey.length; t++) {
//不为空的字段名才取值
if (arrKey[t] != '') {
Ext.getCmp(arrKey[t]).setValue(data[i][arrKey[t]]);
}
}
}
}
}
代码结构比较简单,相对比较好理解。主要是调用这个方法的位置要知道,调用这个方法也是在控件的方法GetExtAttr(TableName, data)中来调用的。可以参见上面这个方法所粘贴的代码(绿色字体标记部分)。
至此,扩展属性在业务单据中所有代码、方法的阐述说明基本已经完成,但是还是有必要把列表中通过扩展属性(在列表中显示为‘其他条件’,以下将以‘其他条件’为代名词来阐述相关的方方面面)来检索数据这一块功能的说明补充上去。
以采购申请单据为例,先看其他条件在页面中的显示效果:
图示5
可以看到,其他条件在列表检索条件中显示为一个组合控件的形式,左边部分是一个下拉框,而右边是一个可以输入值的文本框。其实,如果采购申请单如果没有设置相应的扩展属性的话,这个组合控件将不会显示,除非设置了扩展属性才会看到上图所示的效果。这个组合控件中下拉框中的数据是在页面初始化的时候加载过来的,数据是和扩展属性自定义项完全对应的。
这个组合控件我们设计的时候是把它放在了一个用户控件中以便各个所需页面快捷省力的调用。那么对用户控件的引用以及初始化在上面的阐述中已经提及到了,这里不再做赘述。需要注意的是在列表的内置类中需要设置以下其他条件控件所需的几个属性的值初始化,直接粘代码:
GetBillExAttrControlNew1.TableName = "officedba.PurchaseApply";
string EFIndex = Request.QueryString["EFIndex"];
string EFDesc = Request.QueryString["EFDesc"];
GetBillExAttrControlNew1.ExtIndex = EFIndex;
GetBillExAttrControlNew1.ExtValue = EFDesc;
GetBillExAttrControlNew1.SetExtControlValue();
很明显,TableName属性是要根据不同的业务单据来进行设定的,SetExtControlValue()方法在这里调用执行之后会把相应的属性和字段等信息初始化,具体可以看系统中相关文件的代码,这部分是采用的原来的设计。