概述
本示例是一个常见的产品目录树的演示。本示例链接如下:
准备工作
新建一工程producttree,并且配置好数据库,具体步骤参考3.1.2节。
开发步骤
添加Dataset
步骤1:添加一Common ViewModel,文件名为ProductTree。
步骤2:添加该ViewModel的实现,代码如下:
import java.util.List; import com.bstek.dorado.data.Dataset; import com.bstek.dorado.data.ParameterSet; import com.bstek.dorado.data.Record; import com.bstek.dorado.data.RecordIterator; import com.bstek.dorado.data.db.DBStatement; import com.bstek.dorado.utils.variant.VariantSet; import com.bstek.dorado.view.DefaultViewModel; /** * ProductTreeViewModel */ public class ProductTreeViewModel extends DefaultViewModel { protected void doUpdateData(ParameterSet parameters, ParameterSet outParameters) throws Exception { DBStatement stCategory = new DBStatement(); stCategory.setSql(DBStatement.SELECT, "category"); DBStatement stDelCategory = new DBStatement(); stDelCategory.setSql(DBStatement.DELETE, "category"); DBStatement stDelProduct = new DBStatement(); stDelProduct.setSql(DBStatement.DELETE, "product"); try { Dataset datasetCategory = getDataset("datasetCategory"); RecordIterator iter = datasetCategory.recordIterator(); iter.setVisibility(Dataset.FILTER_DELETED); while (iter.hasNext()) { Record record = iter.nextRecord(); deleteChildCategory(record.getString("category_id"), stCategory, stDelCategory, stDelProduct); } } finally { stCategory.close(); stDelCategory.close(); stDelProduct.close(); } super.doUpdateData(parameters, outParameters); } private void deleteChildCategory(String categoryId, DBStatement stCategory, DBStatement stDelCategory, DBStatement stDelProduct) throws Exception { stCategory.parameters().setString("parent_id", categoryId); List list = stCategory.queryForList(); int size = list.size(); for (int i = 0; i < size; i++) { VariantSet category = (VariantSet) list.get(i); deleteChildCategory(category.getString("category_id"), stCategory, stDelCategory, stDelProduct); } stDelCategory.parameters().setString("category_id", categoryId); stDelCategory.execute(); stDelProduct.parameters().setString("category_id", categoryId); stDelProduct.execute(); } }
步骤3:添加一CustomDataset,id设置为datasetRoot,添加两个字段,分别为category_id,category_name。
步骤4:为datasetRoot添加一Dataset Listener,代码如下:
import com.bstek.dorado.data.AbstractDatasetListener; import com.bstek.dorado.data.Dataset; /** * ProductTree_datasetRootListener */ public class ProductTree_datasetRootListener extends AbstractDatasetListener { public void afterLoadData(Dataset dataset) throws Exception { dataset.insertRecord(); dataset.setString("category_id", "$null"); dataset.setString("category_name", "<产品目录>"); } }
步骤5:添加一AutoSqlDataset,选择Category表,选择所有列,属性设置如下:
属性 | 值 |
---|---|
id | datasetCategory |
originTable | category |
keyFields | category_id |
为AutoSqlDataset的Field的category_id和category_name添加"Vlidator-Required",添加位置如下图所示:
为AutoSqlDataset添加一BaseMatchRule,属性设置如下:
属性 | 值 |
---|---|
level | 1 |
dataType | string |
value | :parent_id |
escapeEnabled | true |
table | category |
originField | parent_id |
operator | = |
为AutoSqlDataset添加一Parameter,属性设置如下:
属性 | 值 |
---|---|
name | parent_id |
value | $null |
为datasetCategory的beforeDelete事件添加如下代码:
var category_id = parseInt(record.getValue("category_id")); if (record.getString("parent_id") == "" && (category_id == 1 || category_id == 2 || category_id == 3)) { return "处于演示数据的安全考虑,本例不允许您删除顶层的分类!";}
步骤6:添加一AutoSqlDataset,选择Product表,选择所有字段,属性设置如下:
属性 | 值 |
---|---|
id | datasetProduct |
originTable | product |
keyFields | product_id |
为AutoSqlDataset的Field的product_id、category_id和product_name添加"Vlidator-Required"
为AutoSqlDataset添加三个BaseMatchRule,属性设置分别如下:
属性 | 值 |
---|---|
level | 1 |
dataType | string |
value | :category_id |
escapeEnabled | true |
table | product |
originField | category_id |
operator | = |
属性 | 值 |
---|---|
level | 1 |
dataType | string |
value | :product_id |
escapeEnabled | true |
table | product |
originField | product_id |
operator | = |
属性 | 值 |
---|---|
level | 1 |
dataType | string |
value | :product_name |
escapeEnabled | true |
table | product |
originField | product_name |
operator | like |
添加DataTree
步骤1:添加一DataTree,属性设置如下:
属性 | 值 |
---|---|
id | treeProduct |
height | 100% |
width | 100% |
draggable | true |
步骤2:为treeProduct添加一Simple Tree Level,属性设置如下:
属性 | 值 |
---|---|
name | root |
dataset | datasetRoot |
labelField | category_name |
expanded | true |
步骤3:为root添加一Recursive Tree Level,属性设置如下:
属性 | 值 |
---|---|
name | category |
dataset | datasetCategory |
recursiveKeyFields | category_id |
recursiveKeyParameters | parent_id |
labelField | category_name |
detailKeyParameters | parent_id |
masterKeyFields | category_id |
步骤4:为product添加一Simple Tree Level,属性设置如下:
属性 | 值 |
---|---|
name | product |
dataset | datasetProduct |
masterKeyFields | category_id |
detailKeyParameters | category_id |
labelField | product_name |
hasChild | false |
步骤5:为treeProduct的beforeCurrentChange事件添加如下代码:
if (node.getLevel() == 1) { return new AbortException(); }
为treeProduct的afterCurrentChange事件添加如下代码:
if (node == null) return; if (node.getTreeLevel().getName() == "category") { tabsetDetail.setCurrentTab("category"); } else { tabsetDetail.setCurrentTab("product"); }
为treeProduct的onDragOver事件添加如下代码:
var draggingLevel = draggingObject.getTreeLevel().getName(); var targetLevel = targetObject.getTreeLevel().getName(); if (draggingLevel == "category") { return (targetLevel == "root" || targetLevel == "category"); } else if (draggingLevel == "product") { return (targetLevel == "category"); }
为treeProduct的onDragEnd事件添加如下代码:
var draggingLevel = draggingObject.getTreeLevel().getName(); var targetLevel = targetObject.getTreeLevel().getName(); var draggingRecord = draggingObject.getRecord(); var targetRecord = targetObject.getRecord(); if (draggingLevel == "category") { if (targetLevel == "root") { draggingRecord.setValue("parent_id", null); } else { draggingRecord.setValue("parent_id", targetRecord.getValue("category_id")); } } else if (draggingLevel == "product") { draggingRecord.setValue("category_id", targetRecord.getValue("category_id")); } return true;
添加AutoForm和Button
步骤1:添加一AutoForm,属性设置如下:
属性 | 值 |
---|---|
id | formCategory |
dataset | datasetCategory |
选中formCategory,点击字段生成按钮。
步骤2:添加一Button,属性设置如下:
属性 | 值 |
---|---|
id | buttonAddCategory |
value | 添加分类 |
为buttonAddCategory的onClick事件添加如下代码:
if (!validateCurrentRecord()) return; var record = datasetCategory.insertRecord(); var currentNode = treeProduct.getCurrentNode(); var parentNode = currentNode.getParent(); if (parentNode.getLevel() > 0) { var parentRecord = parentNode.getRecord(); var parent_id = parentRecord.getValue("category_id"); if (parent_id == "$null") parent_id = null; record.setValue("parent_id", parent_id); } var node = new RecordTreeNode(record, currentNode.getTreeLevel()); parentNode.addNode(node); treeProduct.setCurrentNode(node);
步骤3:添加一Button,属性设置如下:
属性 | 值 |
---|---|
id | buttonAddChildCategory |
value | 添加子分类 |
为buttonAddChildCategory的onClick事件添加如下代码:
if (!validateCurrentRecord()) return; var currentNode = treeProduct.getCurrentNode(); treeProduct.expandNode(currentNode); var record = datasetCategory.insertRecord(); var parentRecord = currentNode.getRecord(); record.setValue("parent_id", parentRecord.getValue("category_id")); var node = new RecordTreeNode(record, currentNode.getTreeLevel()); currentNode.addNode(node); treeProduct.setCurrentNode(node);
步骤4:添加一Button,属性设置如下:
属性 | 值 |
---|---|
id | buttonDelCategory |
value | 删除分类 |
为buttonDelCategory的onClick事件添加如下代码:
if (confirm("确定要删除此产品分类以及其中的所有子分类和产品吗?")) { datasetCategory.deleteRecord(); }
步骤5:添加一Button,属性设置如下:
属性 | 值 |
---|---|
id | buttonAddChildProduct |
value | 添加子产品 |
为buttonAddChildProduct的onClick事件添加如下代码:
if (!validateCurrentRecord()) return; var currentNode = treeProduct.getCurrentNode(); treeProduct.expandNode(currentNode); var record = datasetProduct.insertRecord(); var parentRecord = currentNode.getRecord(); record.setValue("category_id", parentRecord.getValue("category_id")); var node = new RecordTreeNode(record, currentNode.getTreeLevel().getTreeLevel("product")); currentNode.addNode(node); treeProduct.setCurrentNode(node);
步骤6:添加一AutoForm,属性设置如下:
属性 | 值 |
---|---|
id | formProduct |
dataset | datasetProduct |
选中formProduct,点击字段生成按钮。
步骤7:添加一Button,属性设置如下:
属性 | 值 |
---|---|
id | buttonAddProduct |
value | 添加产品 |
为buttonAddProduct的onClick事件添加如下代码:
if (!validateCurrentRecord()) return; var record = datasetProduct.insertRecord(); var currentNode = treeProduct.getCurrentNode(); var parentNode = currentNode.getParent(); var parentRecord = parentNode.getRecord(); record.setValue("category_id", parentRecord.getValue("category_id")); var node = new RecordTreeNode(record, currentNode.getTreeLevel()); parentNode.addNode(node); treeProduct.setCurrentNode(node);
步骤8:添加一Button,属性设置如下:
属性 | 值 |
---|---|
id | buttonDelProduct |
value | 删除产品 |
为buttonDelProduct的onClick事件添加如下代码:
if (confirm("确定要删除此产品吗?")) { datasetProduct.deleteRecord(); }
步骤9:为View的function添加如下代码:
function validateCurrentRecord() { if (tabsetDetail.getCurrentTab().getName() == "category") { return datasetCategory.postRecord(); } else { return datasetProduct.postRecord(); } }
为View的onLoad事件添加如下代码:
var current = datasetCategory.getCurrent(); if (current != null) { var node = treeProduct.findNodeByRecord(current); if (node != null) treeProduct.setCurrentNode(node); }
为View的onUnLoad事件添加如下代码:
if (commandSave.isDirty()) { if (confirm("本页面中有未保存的数据.\n您希望在离开之前对这些数据进行保存吗?")) { commandSave.execute(); } }
添加Command和Button
步骤1:添加一UpdateCommand,id设置为commandSave。
选中commandSave,为其添加两个DatasetInfo,分别为datasetCategory、datasetProduct。
步骤2:添加一Button,属性设置如下:
属性 | 值 |
---|---|
id | buttonSave |
command | commandSave |
value | 保存所有修改 |
创建Jsp页面
生成Jsp页面以后再编辑一下布局,最后结果如下:
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="http://www.bstek.com/dorado" prefix="d" %> <html> <head> </head> <body style="margin: 0; overflow: hidden"> <d:View config="ProductTree"> <d:Layout type="border"> <d:Pane position="center"> <d:SplitPanel id="splitpanel1" orientation="horizontal" width="100%" height="100%" showButtons="true"> <d:DataTree id="treeProduct" /> <d:Splitter /> <d:TabSet id="tabsetDetail" showFrame="false"> <d:Tab name="category" visible="false" padding="12"> <d:Layout type="Hflow" height="30"> <d:Pane> <d:Button id="buttonAddCategory" /> </d:Pane> <d:Pane> <d:Button id="buttonAddChildCategory" /> </d:Pane> <d:Pane> <d:Button id="buttonDelCategory" /> </d:Pane> <d:Pane> <d:Button id="buttonAddChildProduct" /> </d:Pane> </d:Layout> <d:AutoForm id="formCategory" /> </d:Tab> <d:Tab name="product" visible="false" padding="12"> <d:Layout type="Hflow" height="30"> <d:Pane> <d:Button id="buttonAddProduct" /> </d:Pane> <d:Pane> <d:Button id="buttonDelProduct" /> </d:Pane> </d:Layout> <d:AutoForm id="formProduct" /> </d:Tab> </d:TabSet> </d:SplitPanel> </d:Pane> <d:Pane position="bottom" align ="right" padding="6" style="background-color: #f0f0f0"> <d:Button id="buttonSave" /> </d:Pane> </d:Layout> </d:View> </body> </html>
查看运行效果
启动服务器后,浏览效果如下:
点击左边不同的节点,可以在右侧对该节点进行操作。
知识点
本示例的知识点为DataTree部分。关于DataTree可以参考《dorado 5 组件详解 1.1》第二部分的B部分的第2部分。
Attachments:
worddav6a466e841cb8c701eb89a2c12fd860c5.png (image/png)