思路描述
- 创建一个动态的Component(输入框,日期选择,下拉框)列表,与table的列绑定(动态的Component见1)
- 声明一个EditRowModel与Component对应绑定当Component组件变化时,双向绑定到EditRowModel中
- 编辑某一行时,将该行锁绑定的row对象值复制到EditRowModel中,同时将Component组件复制到对应的tableCell中,此时就会显示编辑行
- 结束编辑时,将EditRowModel复制倒正在编辑行对应的row对象中。
代码TableFormRowEdit
//表格编辑
function TableFormRowEdit(option, formCom, dataTag, pro_tableId,isMul) {
//配置
var self = this;
var fieldCtrls = []; //编辑列
// var tempCtrlComponent = {};//临时组件列表
// option.data.FormModel.DeleteRows = [];
//增加行
option.methods["FormModel_"+dataTag+"_addRow"] = function (newRow,index) {
//如果非编辑状态不触发
if (!formCom.vm.isEditing) return false;
if (isMul) {
self.initEditDataModel(function () {
if (index == undefined) { index = formCom.vm.DataModel[dataTag].DataRows.length; }
var curRow = formCom.addRow(dataTag, newRow, index);
Vue.nextTick(function () {
self.editRow(curRow, index);
});
});
} else {
self.endEdit();
formCom.vm.selectedIndex = -1;
self.initEditDataModel(function () {
index = formCom.vm.DataModel[dataTag].DataRows.length;
formCom.addRow(dataTag, newRow, index);
});
}
};
//编辑行
option.methods["FormModel_" + dataTag + "_modifyRow"]= function (mRow, index) {
//如果非编辑状态不触发
var vm = this;
if (!vm.isEditing) return false;
self.endEdit();
if (mRow.DataState == "UA") {
mRow.DataState == "A";
} else if (mRow.DataState == "U") {
mRow.DataState == "M";
}
self.beginEdit(mRow, index);
}
//选中行
option.methods["FormModel_" + dataTag + "_selectRow"] = function (mRow, index) {
var e = window.event; //当前事件
var vm = this;
//判断
if (vm.selectedIndex == index) { return false; }
//
vm.selectedIndex = index;
vm["FormModel_" + dataTag + "_modifyRow"](mRow, index);
//获取焦点
window.setTimeout(function () {
var el = e.target;
if (el.tagName == "DIV") { el = el.parentNode; }
$(el).find("input").trigger("focus");
}, 0);
}
//移除行
option.methods["FormModel_" + dataTag + "_removeRow"] = function (index) {
if (!formCom.vm.isEditing) return false;
if (index == undefined) index = formCom.vm.selectedIndex;
var dataX= formCom.vm.DataModel[dataTag];
if (dataX.DataRows.length>index > -1) {
if (!dataX.deletedRows) dataX.deletedRows = [];
var mRow = dataX.DataRows[index];
if (mRow.DataState == "A" || mRow.DataState == "UA") {
} else {
mRow.DataState = "D";
dataX.deletedRows.push(mRow);
}
self.removeRow(index);
}
}
//设置编辑列
this.setFieldCtrl = function (fieldIndex, ctrl) {
if (typeof (fieldIndex) != "number") { return; }
if (fieldIndex < 0) return;
if (fieldIndex > fieldCtrls.length - 1) { //填充生成序列
for (var i = fieldCtrls.length - 1; i < fieldIndex; i++) {
fieldCtrls.push("");
}
}
//插入
var oCtrl = ctrl;
if (oCtrl) fieldCtrls.splice(fieldIndex, 1, oCtrl);
}
//开启编辑
var obj_tb;
var oldRow;
this.beginEdit = function (mRow, index) {
//缓存原对象
if (!mRow || oldRow == mRow) {
return;
}
oldRow = mRow;
var rootVM = formCom.vm;
rootVM.FormModel[dataTag].EditRowModel = JSON.parse(JSON.stringify(mRow));
obj_tb = $("#" + pro_tableId)[0];
if (!obj_tb) { return; }
//以下生成编辑框
var iLen = fieldCtrls.length;
var oCells = obj_tb.tBodies[0].rows[index].cells;
for (var i = 0; i < iLen; i++) {
var o = fieldCtrls[i];
if (!o || !o.type) { continue; } //o不存不处理
var currentCell = oCells[i];
//生成插入元素
if (o.type == "DropList" || o.type == "TextBox" || o.type == "DatePick" || o.type == "CheckBox" ) {
var $ov = $(oCells[i].firstChild); //原内容隐藏
if ($ov) { $ov.hide() } else { $(currentCell).text(""); };
(function (o, currentCell) {
var component;
if (!o.component) {
var cOption = {
propsData: {
myValue: mRow.DataRow[o.fieldName],
valueEmit: function (val) { //与外面mrow联动
// .DataRow[o.fieldName] = val;
var editRow = rootVM.FormModel[dataTag].EditRowModel;
return editRow;
}
}
};
o.component = new o.extendComponent(cOption).$mount()
}
component = o.component;
component.myValue = mRow.DataRow[o.fieldName];
currentCell.appendChild(component.$el);
})(o, currentCell);
}
}
};
//结束编辑
this.endEdit = function (mRow, index) {
if (!obj_tb) obj_tb = $("#" + pro_tableId)[0];
if (!obj_tb) { return; }
var iLen = fieldCtrls.length;
// var oCells = obj_tb.tBodies[0].rows[index].cells;
//恢复现场
var editRow = formCom.vm.FormModel[dataTag].EditRowModel
if (editRow) {
if (oldRow.DataRow) oldRow.DataRow = JSON.parse(JSON.stringify(editRow.DataRow));
}
for (var i = 0; i < iLen; i++) {
var o = fieldCtrls[i];
if (o && o.component && o.component.$el) {
var oCell = o.component.$el.parentNode; //td
if (!oCell) continue;
oCell.removeChild(oCell.lastChild);
var $ov = $(oCell.firstChild); //原内容恢复
$ov.show();
//if (mRow) {
// mRow.DataRow[o.name] = o.component.myValue;
//} else {
//if ($ov.length > 0) {
// $ov.text(o.component.myValue);
//} else {
// oCell.innerText = o.component.myValue;
//}
// }
}
}
oldRow = {};
};
//移除行并返回移除的对象(传入index或对象row)
this.removeRow = function (x) {
var datarows = formCom.vm.DataModel[dataTag].DataRows;
var index = -1;
var mRow = null;
if (typeof x == "number") {
index = x; mRow = datarows[index];
}
if (typeof x == "object") {
mRow = x;
for (var i = datarows.length; i > 0; i--) {
if (datarows[i - 1] == mRow) {
index = i - 1; break;
}
}
}
if (index > -1 && mRow) {
datarows.splice(index, 1);
}
}
//初始化编辑行,制造一个空的datarow
this.initEditDataModel = function (callBack) {
if (!window.tempObjModel) {
window.tempObjModel = {};
}
if (window.tempObjModel[dataTag]) { if (typeof (callBack) == "function") callBack(); return; }
var dataRows = formCom.vm.DataModel[dataTag].DataRows;
if (dataRows.length > 0) {
var tempObj = {};
$.extend(true, tempObj, window["CustomerModel_" + dataTag] || dataRows[0]);
tempObj.DataState = "UA"; //中间态
delete tempObj["IsOpenEdit"]; delete tempObj["_uid"]; //删除附加属性
formCom.clearTemplateModel(tempObj);
window.tempObjModel[dataTag] = tempObj;
if (typeof (callBack) == "function") callBack();
} else {
var url = formCom._baseUrl;
var action = formCom.getAction;
if (!action) action = "/addData";
url = url + action;
Vue.$http.get(url, {}, function (data, status) {
var tempObj = {}; ;
$.extend(true, tempObj, window["CustomerModel_" + dataTag] || data[dataTag].DataRows[0]);
tempObj.DataState = "UA"; //中间态
formCom.clearTemplateModel(tempObj);
window.tempObjModel[dataTag] = tempObj;
if (typeof (callBack) == "function") callBack();
});
}
}
//******以下单表格编辑start*******************
if (isMul) {
var oldRowModels = {}; //缓存编辑的旧值
//关闭编辑框--允许多行有用
//this.closeEdit = function (mRow, index) {
// if (!obj_tb) obj_tb = $("#" + pro_tableId)[0];
// if (!obj_tb) { return; }
// var iLen = fieldCtrls.length;
// //恢复现场-还原现场
// for (var i = 0; i < iLen; i++) {
// var o = fieldCtrls[i];
// var component = tempCtrlComponent["row_" + mRow._uid + "_index_" + i];
// if (o && component && component.$el) {
// var oCell = component.$el.parentNode; //td
// if (!oCell) continue;
// oCell.removeChild(oCell.lastChild); //解除引用
// var $ov = $(oCell.firstChild); //原内容恢复
// if ($ov) { $ov.show(); } else { $(oCell).text(mRow[o.DataRow.name]); }
// component = null;//销毁对象
// tempCtrlComponent["row_" + mRow._uid + "_index_" + i] = null;
// }
// }
// //释放缓存
// oldRowModels["index_" + mRow._uid] = undefined;
// oldRow = {};
// }
option.methods["FormModel_" + dataTag + "_cancelEdit"] = function (mRow, index) {
var oRow = oldRowModels["index_" + mRow._uid];
if (oRow) {
mRow.DataRow = oRow.DataRow;
// self.closeEdit(mRow, index);
self.switchEditBtn(mRow, index);
}
};
//切换编辑按钮就
this.switchEditBtn = function (mRow, index) {
if (mRow.IsOpenEdit == undefined) {
Vue.set(mRow, "IsOpenEdit", true);
} else if (mRow.IsOpenEdit) {
mRow.IsOpenEdit = false;
} else {
mRow.IsOpenEdit = true;;
}
};
var _uidIndex = 0;
//编辑行
this.editRow = function (mRow, index) {
mRow._uid = ++_uidIndex; //作为标识
// self.beginEdit(mRow, index);
oldRowModels["index_" + mRow._uid] = jQuery.extend(true, {}, mRow); //缓存编辑行
self.switchEditBtn(mRow, index);
if (mRow.DataState == "U") {
mRow.DataState = "M";
}
};
option.methods["FormModel_" + dataTag + "_editRow"] = self.editRow;
//**********配置相关start***********
formCom.setVerifyFormula(dataTag);
formCom.injectVerifyMethod(function (newData, vm) {
var msg = ""
if (!window.verifyFormula) { return msg; }
var selfRegular = window.verifyFormula; //获取验证
if (newData[dataTag] && selfRegular[dataTag] && selfRegular[dataTag].length > 0) {
Vue.verifyData(newData[dataTag].DataRows, selfRegular[dataTag], function (f, i) {
// vm.ErrorModel[datatag][f.compareColumn] = f.msg; //通过
msg = msg + f.msg + '<br>';
}, function (f, i) {
// vm.ErrorModel[datatag][f.compareColumn] = ""; //不通过
});
}
if (msg) { dialogBox.openDialog(msg) };
return msg
});
//**********配置相关 end**********
//保存单行
this.saveData = function (mRows, backFunc) {
//组织数据
var newData = { DataState: 'M' };
newData[dataTag] = {
DataRows: [],
DataState: "U",
Type: ""
};
for (var i = 0; i < mRows.length; i++) {
var newRow = jQuery.extend(true, {}, mRows[i]);
newData[dataTag].DataRows.push(newRow);
}
if (!formCom.fireEvent("On_SaveData", newData)) return; //事前savedata
//以下验证
var isVerify = formCom.verifyData(newData, formCom.vm);
if (isVerify) { return; }
var url = formCom._baseUrl;
if (formCom.postAction) url += formCom.postAction;
var jsonString = JSON.stringify(newData);
formCom.post(url, jsonString
, formCom["whenSaveData"]
, function (data) {
dialogBox.openDialog(data.MsgErr);
if (formCom["whenSaveDataFail"]) formCom["whenSaveData"](data);
}
, backFunc);
}
this.saveRow = function (mRow,index) {
var iLen = fieldCtrls.length;
//获取新数据
//for (var i = 0; i < iLen; i++) {
// var o = fieldCtrls[i];
// var component = tempCtrlComponent["row_" + mRow._uid + "_index_" + i];
// if(o && component && component.$el) {
// mRow.DataRow[o.name] = component.myValue;
// }
//}
self.saveData([mRow], function (data) {
//保存成功后
mRow.DataRow = data[dataTag].DataRows[0].DataRow;
// self.closeEdit(mRow, index);
self.switchEditBtn(mRow, index);
});
}
option.methods["FormModel_" + dataTag + "_saveRow"] = self.saveRow;
//删除行
this.deleteRow = function (mRows, callBack) {
//一
if (Object.prototype.toString.call(mRows) != '[object Array]') {
mRows = [mRows];
}
var newRows = [];
for (var i = 0; i < mRows.length; i++) {
var mRow = mRows[i];
if (mRow.DataState == "A" || mRow.DataState == "UA") {
self.removeRow(mRow);//直接移除
} else {
mRow.DataState = "D";
newRows.push(mRow);
}
}
if (newRows.length == 0) { return; }
if (!confirm("确认要删除吗?")) {
return;
}
self.saveData(newRows, function (data) {
//保存成功后
if (typeof callBack == "function") { callBack(data); };
formCom.fireEvent("When_DeleteRow", data); //删除成功后抛出
});
}
option.methods["FormModel_" + dataTag + "_deleteRow"] = self.deleteRow;
//重写formCom的search 防止
var oldSearch = formCom.searchData;
formCom.searchData = function (searchItem, callBack) {
//是否有编辑状态
var rows = formCom.vm.DataModel.DataA.DataRows;
for (var i = 0, len = rows.length; i < len; i++) {
var row = rows[i];
if (row.IsOpenEdit) {
alert("还有正在编辑的行,请保存或取消后继续");
return;
}
}
oldSearch(searchItem, callBack);
}
}
//******单表格编辑end*******************
}
使用
var tableEdit = new TableFormRowEdit(option, formCom, "DataB", "proof_table");
tableEdit.setFieldCtrl(1, comfactory.createTextBox(formCom, "CellPhone"));
//option vue参数
//formCom 表单编辑对象》下面讲
//"DataB",列表行对应的key
//"proof_table" tableid
//html如下
<tr v-for="(p,$index) in DataModel.DataB.DataRows" :key="p.DataRow.CompanyContactsID"
v-on:click="FormModel_DataB_selectRow(p,$index)">
<td>
<div class="tab_inner_txt" vfrequired="/\S/" vferrormsg="[姓名]必填"
v-text="p.DataRow.ContactsName">
</div>
</td>
<td>
<div vfrequired="/^$|^1(3|4|5|6|7|8|9)\d{9}$/" vferrormsg="[联系人号码]格式错误" class="tab_inner_txt" v-text="p.DataRow.CellPhone"></div>
</td>
<td>
<div class="tab_inner_txt" v-text="p.DataRow.Email"></div>
</td>
<td>
<div class="tab_inner_txt" v-text="p.DataRow.QQ"> </div>
</td>
<td>
<div class="tab_inner_txt" v-text="p.DataRow.WeChat"> </div>
</td>
<td>
<div class="tab_inner_txt" v-text="p.DataRow.JobDescription"> </div>
</td>
<td>
<div class="tab_inner_txt" v-text="p.DataRow.IsPublic==1?'是':'否'"> </div>
</td>
</tr>
整体类描述
- vf-*** vue插件,实现基本下拉框,日期选择等vue组件
- VueFormComponent 利用Vue.extend()动态生产VueComponent
- TableFormRowEdit 绑定table、VueComponent、vue.Data,实现表格编辑
- VueFormModel 表单基本操作对象-负责实际操作从后台获取数据绑定页面,从页面获取数据发送到后台,自动绑定vue.data与页面组件,实现get、set、search、verifyData等功能,
- SingleFormModel 组合VueFormModel实现单表
- ItemFormModel 组合VueFormModel实现表头表体
- VueManager 分为初始化vue,配置参数,provide,等各项功能
- DataSetModel 装载数据类