項目開發中遇到的一個實際且實用的功能,就是對應一個項目數據,需要配套的屬性組數據,這一系列的屬性組數據是對項目數據的補充,說白了就是一個可以拓展該項目的其它信息,來進行保存。
實際需求
一個項目,可能對對應多個屬性組,屬性組的展示方式和一些特性可以設置,根據設置的特性來動態的生成該模塊,需要實現的功能是:
- 屬性組可能是表單或者表格,但是無論哪種展示方法,實際的數據都是保存在同一張表中
- 屬性可能為空,也可能為一個或者多個
- 必須以Tab頁的方式展示
4.每一個屬性組都可以單獨的進行編輯,更新,保存,刪除等操作
問題分析
技術的大方向是固定的,即使用freeMark模板技術來進行動態生成前端代碼,包括UI和js的邏輯代碼。
特別注意點:
整個功能需要在系統中的多個頁面進行調用,所以需要抽象為一個獨立的頂層模塊,并且不是實際依賴實際頁面的數據。所以最后抽象為一個java方法,將必要的數據以參數的形式傳遞,然后加載ftl模板,生成前端代碼,最后添加到請求的頁面中去,完成整個邏輯。
//前端調用形式
${attrGroupProvider.getAttrGroup(base,"hpm.impl.dto.Project","projectId","${projectId!0}",attributeGroups)}
實際開發細節問題的思路:
思路整理分析
---
1. 根據提供的接口,拿到該項目設置的屬性組頭表ID結合
2. 拿到集合,查到集合對應的屬性組的集合,存儲進
問題1:多個集合組,數據存儲形式
> 解決思路:map<屬性頭表dto,List<屬性dto>>
3. java加載ftl模板,根據參數,初始化出來界面‘
- map不為空,就建立tab標簽頁組件
- 遍歷map,創建tab頁頭和對應的div
- 根據屬性組頭類型屬性,確定加載grid或者form組
- form組值遍歷循環,添加為input即可
問題2:拿到屬性組加載對應的grid
> 屬性頭id-》屬性組配置-》配置初始化grid和數據源的代碼
4. 頁面初始化完成,進行數據拉取綁定到viewModel,流程完成
項目新建頁面整體流程
---
請求方法controller請求,三種情況
- 項目id
項目id是查看項目明細數據,先獲取模板id,初始化viewAndModel,獲取項目明細數據配置字段的數據,初始化項目明細數據的配置字段顯示
接下來是屬性組配置,此時有項目id,獲取到項目的dto,調用屬性組接口,獲取數據,初始化配置數據頁面
- 模板id
模板id,獲取模板配置數據,初始化頁面,拉取默認字段
獲取屬性組,同上
- lineId
行表id,獲取lineDto,獲取模板id,加載模板數據
模板代碼:
java部分
public String getAttrGroupByDto(RequestContext requestContext,String dtoFullName,String pkName,String primaryKey) throws IOException, TemplateException{
//根據條件獲取要展示的屬性組
List<AttributesGroup> attributeGroups = null;
try {
String str = dtoFullName.replace("dto", "service");
String serviceName = str.substring(0, str.lastIndexOf(".") + 1) + "I" + str.substring(str.lastIndexOf(".") + 1) + "Service";
String serviceImplName = serviceName.substring(serviceName.lastIndexOf(".")+2).substring(0,1).toLowerCase() + serviceName.substring(serviceName.lastIndexOf(".")+2).substring(1) + "Impl";
if(attributeGroups == null ){
Class<?> dtoClass = Class.forName(dtoFullName);
Object dtoObj = dtoClass.newInstance();
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
Object serviceImpl = wac.getBean(serviceImplName, Class.forName(serviceName));
Method selectByPrimaryKey = serviceImpl.getClass().getDeclaredMethod(QUERY_METHOD_NAME, dtoClass);
if(!"".equals(primaryKey)) {
Field nameField = dtoClass.getDeclaredField(pkName);
nameField.setAccessible(true);
nameField.set(dtoObj, Long.parseLong(primaryKey));
}
Object resultDto = selectByPrimaryKey.invoke(serviceImpl,dtoObj);
if(resultDto == null){
attributeGroups = attributesAssignService.selectGroupsByBaseDTO((BaseDTO) dtoObj);
}else
{
attributeGroups = attributesAssignService.selectGroupsByBaseDTO((BaseDTO) resultDto);
}
}
} catch (Exception e) {
e.printStackTrace();
return "<p>屬性組查詢失敗</p>";
}
if(attributeGroups == null){
return "";
}
return getAttrGroup(requestContext,dtoFullName,pkName,primaryKey,attributeGroups);
}
public String getAttrGroup(RequestContext requestContext,String dtoFullName,String pkName,String primaryKey,List<AttributesGroup> attributeGroups) throws IOException, TemplateException{
String extUrl = dtoFullName.substring(dtoFullName.lastIndexOf(".")+1).substring(0,1).toLowerCase()+ dtoFullName.substring(dtoFullName.lastIndexOf(".")+1).substring(1)+"Ext";
if(attributeGroups == null){
return "";
}
Template template = getConfiguration().getTemplate("AttributeGroup.ftl");
try(StringWriter out = new StringWriter()){
Map<String, Object> param = new HashMap<>();
Map<String, String> lovDatas = new HashMap<>();
Map<String, List<AttributesCols>> groupsCols = new HashMap<>();
List<String> codeResources = new ArrayList();
AttributesCols attributesCols = new AttributesCols();
for(AttributesGroup group : attributeGroups){
attributesCols.setAttributeGroupId(group.getAttributeGroupId());
List<AttributesCols> attributeRestoutCols= attributesColsService.selectColsByGroupId(attributesCols);
for(AttributesCols col:attributeRestoutCols){
if("LOV".equals(col.getFormatCode())){
if(col.getFormatValue() != null){
String lovData = kendoLovService.getLov(requestContext.getContextPath(),requestContext.getLocale(),col.getFormatValue());
lovDatas.put(col.getFormatValue(),lovData);
}
};
if("LIST".equals(col.getFormatCode())){
if(col.getFormatValue() != null) {
codeResources.add(col.getFormatValue());
}
}
}
groupsCols.put(group.getAttributeGroupId().toString(),attributeRestoutCols);
}
param.put("groupsCols", groupsCols);
param.put("attributeGroups", attributeGroups);
param.put("lovDatas", lovDatas);
param.put("base", requestContext);
param.put("listSources", codeResources);
param.put("pkName", pkName);
param.put("dtoFullName", dtoFullName);
param.put("primaryKey", primaryKey);
param.put("extUrl", extUrl);
template.process(param, out);
out.flush();
String html = out.toString();
return html;
}
}
freeMark部分
<#-- 屬性組動態配置模板 -->
<div class="row" >
<div class="col-md-12">
<h4>屬性組</h4>
<hr/>
</div>
</div>
<#-- 下拉列表取值源 -->
<#if listSources?? >
<#list listSources as ls>
<script src="${base.contextPath}/common/code?${ls+ "Resource"}=${ls}"type="text/javascript"></script>
</#list>
</#if>
<#if groupsCols?? >
<#-- 屬性組數據存在,遍歷創建tab頁 -->
<script>
var groupModel = kendo.observable({
<#-- 創建form綁定對象 -->
<#list attributeGroups as group>
<#if group.displayType == "FORM">
${group.groupInternalName}${group.attributeGroupId}:{
${pkName}:${primaryKey!null},
attributeGroupId:${group.attributeGroupId},
ext1:2
},
<#elseif group.displayType == "GRID">
<#-- 生成grid的操作方法,包括新增,保存,取消-->
${"grid" + group_index + "Insert"}:function(e){
if(typeof(viewModel.model.${pkName}) === "undefined"){
kendo.ui.showInfoDialog({
message: '請先保存,再進行屬性組操作!'
});
return;
}
${"grid" + group_index}.addRow();
},
${"grid" + group_index + "Save"}:function(e){
if(typeof(viewModel.model.${pkName}) === "undefined"){
kendo.ui.showInfoDialog({
message: '請保存先保存項目,再進行屬性組操作!'
});
return;
}
${"grid" + group_index}.saveChanges();
},
${"grid" + group_index + "Cancel"}:function(e){
if(typeof(viewModel.model.${pkName}) === "undefined"){
kendo.ui.showInfoDialog({
message: '請保存先保存項目,再進行屬性組操作!'
});
return;
}
${"grid" + group_index}.cancelChanges();
},
</#if>
</#list>
//以下所有操作,必須保證當前頁面的viewModel里有pkName,否則視為當前沒有已創建項目,會提示:請保存先保存項目,再進行屬性組操作
groupFromsRead:function () {
if(typeof(viewModel.model.${pkName}) === "undefined" || viewModel.model.${pkName} == null){
return;
}
//構造 查詢條件參數
var groups = [
<#list attributeGroups as group>
<#if group.displayType == "FORM">
<#if (attributeGroups?size)-1 == group_index >
{
${pkName}:viewModel.model.${pkName},
attributeGroupId:${group.attributeGroupId}
}
<#else>
{
${pkName}:viewModel.model.${pkName},
attributeGroupId:${group.attributeGroupId}
},
</#if>
</#if>
</#list>
];
$.ajax({
url:"${base.contextPath}/attr/${extUrl}/formQuery",
contentType: "application/json",
type: "POST",
data:kendo.stringify(groups),
success:function(data){
//將數據綁定到form中去
var formatModel = groupModel.toJSON();
var formatGroup;
var group;
for(var modelKey in formatModel){
group = groupModel[modelKey];
var remoteData = data[group.attributeGroupId.toString()];
formatGroup = group.toJSON();
for(var groupKey in remoteData){
if(remoteData[groupKey] != null){
group.set(groupKey,remoteData[groupKey]);
}
}
}
}
})
},
//新建和更新
GroupFromSync:function (formKey) {
if(typeof(viewModel.model.${pkName}) === "undefined"){
kendo.ui.showInfoDialog({
message: '請保存先保存項目,再進行屬性組操作!'
});
return;
}
if(viewModel.model.${pkName} == null){
kendo.ui.showInfoDialog({
message: '請保存先保存項目,再進行屬性組操作!'
});
return;
}
var groupFormValidateResult = $('#'+formKey).kendoValidator({
valid: function (e) {
},
//驗證樣式 默認為default
invalidMessageType : "tooltip"
}).data("kendoValidator").validate();
if(!groupFormValidateResult){
// num數字輸入組件樣式加載會出問題,在這里進行修復
var Numerics = $('#'+formKey).find('.k-numeric-wrap');
for(var i = 0,len = Numerics.length; i < len; i++){
Numeric = Numerics[i];
var child = $($(Numeric).children()[1]);
if((child.val() === undefined || child.val() === null || child.val() === "") && child.attr("required") === "required"){
$(Numeric).addClass("k-valid-custom");
}else{
$(Numeric).removeClass("k-valid-custom");
}
}
// LOV輸入組件樣式加載會出問題,在這里進行修復
var Lovs = $('#'+formKey).find('.k-lov');
for(var i = 0,len = Lovs.length; i < len; i++){
Lov = Lovs[i];
childSpan = $(Lov).children()[0];
var childInput = $($(Lov).children()[1]);
if((childInput.val() === undefined || childInput.val() === null || childInput.val() === "") && childInput.attr("required") === "required"){
$(childSpan).addClass("k-valid-custom");
}else{
$(childSpan).removeClass("k-valid-custom");
}
};
// LOV輸入組件樣式加載會出問題,在這里進行修復
var Lists = $('#'+formKey).find('.k-combobox');
for(var i = 0,len = Lists.length; i < len; i++){
list = Lists[i];
childSpan = $(list).children()[0];
var childInput = $($(list).children()[1]);
if((childInput.val() === undefined || childInput.val() === null || childInput.val() === "") && childInput.attr("required") === "required"){
$(childSpan).addClass("k-valid-custom");
}else{
$(childSpan).removeClass("k-valid-custom");
}
}
return;
}
var groupData = this[formKey];
groupData.set("${pkName}",viewModel.model.${pkName});
$.ajax({
url:"${base.contextPath}/attr/${extUrl}/formSubmit",
contentType: "application/json",
type: "POST",
dataType:"JSON",
data:kendo.stringify(groupData),
success:function(data){
if(data.insert === true || data.update === true){
kendo.ui.showInfoDialog({
message: '保存成功!'
});
var formatGroup = groupData.toJSON();
for(var k in data.${extUrl}){
groupData.set(k,data.projectExt[k]);
}
}else{
kendo.ui.showErrorDialog({
message: '保存失敗!'
});
}
}
});
},
//清空該form,form不支持刪除,提供清空選項,抹掉所有數據
GroupFromClear:function (formKey) {
var groupData = this[formKey];
var col = "ext";
for(var i = 1; i < 51; i++){
groupData.set(col+i, null);
}
}
});
</script>
<div id="tabstrip-groups" style="margin-left:5px;">
<#-- 遍歷,tab頁頭 -->
<ul class="nav nav-tabs">
<#list attributeGroups as group>
<li <#if group_index == 0> class="k-state-active"</#if> >${group.groupDisplayName}</li>
</#list>
</ul>
<#list attributeGroups as group>
<div style="padding: 0px">
<#--表單形式的展示-->
<#if group.displayType == "FORM">
<div class="panel panel-default" style="border: 0px;margin-bottom: 0px">
<div class="panel-heading" style="padding: 4px">
<button style="float: right;margin-left: 5px" type="button" onclick="groupModel.GroupFromClear('${group.groupInternalName}${group.attributeGroupId}')" class="btn btn-warning">
<i class="fa fa-eraser" style="margin-right:3px;"></i>清空</button>
<button style="float: right" type="button" onclick="groupModel.GroupFromSync('${group.groupInternalName}${group.attributeGroupId}')" class="btn btn-success">
<i class="fa fa-save" style="margin-right:3px;"></i>保存</button>
</div>
<div class="panel-body">
<form class="form-horizontal"
id="${group.groupInternalName}${group.attributeGroupId}"
role="form">
<div class="row" style="margin: 0px" >
<#-- 直接獲取id本身沒有任何問題,但是隱式的number轉string的時候,freemark會自動加 “,”
例如: 123345 =》 “123,345” ,這個隱式的問題會導致key錯誤,從而導致找不到key而報錯,所以強制調用 c 方法轉換-->
<#assign cols = groupsCols[group.attributeGroupId?c]>
<#if (cols?size>0) >
<#list cols as col>
<#if col_index%4==0>
<div class="col-md-12">
</#if>
<div class="col-md-3">
<div class="form-group">
<label class="col-md-3 control-label" style="padding: 0px">${col.colDisplayName}</label>
<div class="col-md-9">
<#if col.formatCode == "BOOLEAN">
<input type="checkbox"
<#if col.requiredFlag?? && col.requiredFlag == "Y">
required
</#if>
data-bind="value:${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}"
id="${group.groupInternalName}_${col.colInternalName}"/>
<script>
$("#${group.groupInternalName}_${col.colInternalName}").kendoCheckbox({
checkedValue:'Y',
uncheckedValue:'N'
});
</script>
<#elseif col.formatCode == "DATE">
<input type="text"
<#if col.requiredFlag?? && col.requiredFlag == "Y">
required
</#if>
data-bind="value:${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}"
id="${group.groupInternalName}_${col.colInternalName}"
style="width: 100%;"/>
<script>
$("#${group.groupInternalName}_${col.colInternalName}").kendoDatePicker({
<#if col.formatMask??>
format:"${col.formatMask}"
</#if>
});
<#if col.defaultValue??>
groupModel.set('${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}','${col.defaultValue}');
</#if>
</script>
<#elseif col.formatCode == "DATETIME">
<input type="text"
<#if col.requiredFlag?? && col.requiredFlag == "Y">
required
</#if>
data-bind="value:${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}"
id="${group.groupInternalName}_${col.colInternalName}"
style="width: 100%;"/>
<script>
$("#${group.groupInternalName}_${col.colInternalName}").kendoDateTimePicker({
<#if col.formatMask??>
format:"${col.formatMask}"
</#if>
});
<#if col.defaultValue??>
groupModel.set('${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}','${col.defaultValue}');
</#if>
</script>
<#elseif col.formatCode == "NUM">
<input type="text"
<#if col.requiredFlag?? && col.requiredFlag == "Y">
required
</#if>
data-bind="value:${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}"
id="${group.groupInternalName}_${col.colInternalName}"
style="width: 100%;"/>
<script>
$("#${group.groupInternalName}_${col.colInternalName}").kendoNumericTextBox({
<#if col.formatMask??>
format:"${col.formatMask}"
</#if>
});
<#if col.defaultValue??>
groupModel.set('${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}','${col.defaultValue}');
</#if>
</script>
<#elseif col.formatCode == "LIST">
<script src='${base.contextPath}/common/code?${group.groupInternalName}_${col.colInternalName+ "Resource"}=${col.formatValue}' type="text/javascript"></script>
<select data-role="combobox"
id="${group.groupInternalName}_${col.colInternalName}"
<#if col.requiredFlag?? && col.requiredFlag == "Y">
required
</#if>
data-value-primitive="true"
style="width:100%;"
data-text-field="meaning"
data-value-field="value"
data-bind="value:${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}"
data-source="${col.formatValue+ "Resource"}">
</select>
<script>
<#if col.defaultValue??>
groupModel.set('${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}','${col.defaultValue}');
</#if>
</script>
<#elseif col.formatCode == "LOV">
<input
id="${group.groupInternalName}_${col.colInternalName}"
<#if col.requiredFlag?? && col.requiredFlag == "Y">
required
</#if>
type="text"
data-bind="value:${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}"
style="width: 100%;"/>
</input>
<script>
<#if lovDatas?? && col.formatValue??>
<#assign lovData = lovDatas[col.formatValue]>
<#if lovData??>
$("#${group.groupInternalName}_${col.colInternalName}").kendoLov($.extend(${lovData},
{
select: function(e) {
/*viewModel.model.set('unitId', e.item.unitId);
viewModel.model.set('unitName', e.item.name);*/
}
}));
</#if>
</#if>
</script>
<#else>
<input type="text"
data-bind="value:${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}"
<#if col.requiredFlag?? && col.requiredFlag == "Y">
required
</#if>
id="${group.groupInternalName}_${col.colInternalName}"
class="k-textbox"
style="width: 100%;"/>
<script>
<#if col.defaultValue??>
groupModel.set('${group.groupInternalName}${group.attributeGroupId}.${col.colInternalName}','${col.defaultValue}');
</#if>
</script>
</#if>
</div>
</div>
</div>
<#if (col_index+1)%4==0>
</div>
</#if>
</#list>
</div>
<#else>
<p style="margin: 10px;font-size: 17px">未配置屬性列!</p>
</#if>
</div>
</form>
</div>
</div>
<#--表格形式-->
<#elseif group.displayType == "GRID">
<#assign cols = groupsCols[group.attributeGroupId?c]>
<#if (cols?size>0) >
<div id='${"grid" + group_index}' style="border: 1px;"></div>
<script>
var ${"dataSource" + group_index} = new kendo.data.DataSource({
transport: {
read: {
url: "${base.contextPath}/attr/${extUrl}/gridQuery",
type : "POST",
dataType: "json"
},
update: {
url: "${base.contextPath}/attr/${extUrl}/gridSubmit",
contentType: "application/json",
type: "POST"
},
create: {
url: "${base.contextPath}/attr/${extUrl}/gridSubmit",
contentType: "application/json",
type: "POST"
},
destroy: {
url: "${base.contextPath}/attr/${extUrl}/gridRemove",
contentType: "application/json",
type: "POST"
},
parameterMap: function(options, type) {
if (type !== "read" && options.models) {
var datas = Hap.prepareSubmitParameter(options, type);
for(var i = 0,len = datas.length; i < len ; i++){
datas[i].primaryKey = viewModel.model.${pkName};
datas[i].${pkName} = viewModel.model.${pkName};
}
return kendo.stringify(datas);
} else if (type === "read") {
return Hap.prepareQueryParameter(
{
primaryKey:viewModel.model.${pkName},
<#if primaryKey??>
${pkName}:viewModel.model.${pkName},
<#else>
${pkName}:viewModel.model.${pkName},
</#if>
attributeGroupId:${group.attributeGroupId},
pkName:"${pkName}",
dtoFullName :"${dtoFullName}"
}, options);
}
}
},
requestEnd:function(e){
if((e.type === "create" || e.type === "update") && e.response.success === true){
kendo.ui.showInfoDialog({
message:"保存成功!"
})
}
},
batch: true,
pageSize: 10,
schema: {
data:'rows',
total:'total',
model: {
id: "extId",
fields: {
<#-- 數據源的數據配置 -->
<#list cols as col>
${col.colInternalName}:{
field :"${col.colInternalName}",
<#if col.formatCode == "BOOLEAN">
type:"boolean",
checkedValue: 'Y',
uncheckedValue: 'N',
<#elseif col.formatCode == "GEN">
type:"string",
<#elseif col.formatCode == "DATE">
type:"date",
<#elseif col.formatCode == "DATETIME">
type:"date",
<#elseif col.formatCode == "NUM">
type:"number",
</#if>
<#if col.defaultValue??>
defaultValue: "${col.defaultValue}",
</#if>
<#if col.requiredFlag?? && col.requiredFlag == "Y">
validation: { required: true}
</#if>
},
</#list>
primaryKey: {
type:"number",
field:"${pkName}"
},
dtoFullName: {
type:"string",
field:"dtoFullName",
defaultValue: "${dtoFullName}"
},
pkName: {
type:"string",
field:"pkName",
defaultValue: "${pkName}"
},
attributeGroupId: {
type:"number",
field:"attributeGroupId",
defaultValue: ${group.attributeGroupId}
}
}
}
}
});
var ${"grid" + group_index} =$("#${"grid" + group_index}").kendoGrid({
toolbar: [
{
template:'<span style="float: right" class="btn btn-warning" data-bind="click:${"grid" + group_index + "Cancel"}">' +
'<i class="fa fa-warning"></i>取消</span>'
},
{
template:'<span style="float: right" class="btn btn-success" data-bind="click:${"grid" + group_index + "Save"}">' +
'<i class="fa fa-save" style="margin-right:3px;"></i>保存</span>'
},
{
template:'<span style="float: right" class="btn btn-primary" data-bind="click:${"grid" + group_index + "Insert"}">' +
'<i class="fa fa-plus-square" style="margin-right:3px;"></i>新增</span>'
}
],
dataSource: ${"dataSource" + group_index},
navigatable: false,
height:'100%',
resizable: true,
scrollable: true,
editable:true,
height:350,
selectable:'row',
rownumber: true,
edit:function(e){
if(typeof(viewModel.model.${pkName}) === "undefined"){
kendo.ui.showInfoDialog({
message: '請保存先保存項目,再進行屬性組操作!'
});
preventDefault();
return;
}
if(viewModel.model.${pkName} == null){
kendo.ui.showInfoDialog({
message: '請保存先保存項目,再進行屬性組操作!'
});
preventDefault();
return;
}
},
pageable : {
pageSizes : [5, 10, 20, 50],
refresh : true,
buttonCount: 5
},
columns: [
<#list cols as col>
<#if !col.displayFlag?? || col.displayFlag =="Y" >
{
field: "${col.colInternalName}",
title: '${col.colDisplayName}',
<#if col.formatMask??>
format:'{0:${col.formatMask}}',
</#if>
<#-- 當類型屬于Boolean的時候,checkbox需要居中 -->
<#if col.formatCode == "BOOLEAN">
width:100,
attributes:{
style: "text-align: center;"
}
<#elseif col.formatCode == "LIST">
template: function (dataItem) {
var v = dataItem.${col.colInternalName};
$.each(${col.formatValue+ "Resource"}, function (i, n) {
if ((n.value || '')
== (v || '')) {
v = n.meaning;
return v;
}
});
return v;
},
editor: function (container, options) {
$('<input name="' + options.field + '"/>')
.appendTo(container)
.kendoDropDownList({
dataTextField: "meaning",
dataValueField: "value",
dataSource: ${col.formatValue+ "Resource"}
});
}
<#elseif col.formatCode == "LOV">
template: function (dataItem) {
return dataItem['${col.colInternalName}'] || '';
},
editor: function(container, options){
<#if lovDatas?? && col.formatValue??>
<#assign lovData = lovDatas[col.formatValue]>
<#if lovData??>
$('<input name="${col.colInternalName}" class="k-input k-text-box"/>')
.appendTo(container)
.kendoLov($.extend(${lovData}, {
textField: '${col.colInternalName}',
select:function(e){
},
model: options.model
}));
</#if>
</#if>
}
</#if>
},
</#if>
</#list>
{
title: '刪除',
width : 50,
attributes : {style: "text-align:center"},
headerAttributes: {
style : "text-align: center"
},
command:[{
name:"destroy",
text:""
}]
}
]
}).data("kendoGrid");
</script>
<#else >
<p style="margin: 10px;font-size: 17px">未配置屬性列!</p>
</#if>
</#if>
</div>
</#list>
</div>
<script>
$("#tabstrip-groups").kendoTabStrip({
});
<#-- bind groupModel -->
kendo.bind($('#tabstrip-groups'), groupModel);
<#-- 屬性組form數據的綁定, 讀取,更新和新建操作 -->
groupModel.groupFromsRead();
</script>
<#else>
<div>
</div>
</#if>