锐客网http://bsdn.org/projects
控件字典http://wiki.bsdn.org/pages/viewpage.action?pageId=10355522
APIhttp://dorado7.bsdn.org/jsdoc/
快速入门案例
1,HelloWorld http://bsdn.org/projects/dorado7/deploy/sample-center/com.bstek.dorado.sample.Main.d#33800
映射规律->HelloWorld.view.xml文件的资源路径为com/bstek/dorado/sample/basic/HelloWorld.view.xml。相应的,我访问该视图时使用的URI是/com.bstek.dorado.sample.basic.HelloWorld.d。可以自定义映射。
标签
ViewConfig根节点
View视图
<Button>按钮
<ClientEvent name="onClick">dorado.MessageBox.alert("Hello World!");(js响应)</ClientEvent>点击事件
<Property name="caption">Greeting from Dorado7 ...</Property>按钮名称
</Button>
2,停靠式布局
停靠式布局将整个容器的空间划分为五种,分别是left、top、right、bottom和center,对应五种停靠方式。
当一个控件被分配了上述五种停靠方式中的一种时,它总是尽可能占据那个区域的所有空间,然后将剩余的空间留给后面的控件。
DockLayout中允许除center之外的每一种停靠方式出现多次,具体空间被如何划分取决于它们被添加到布局管理器的顺序。
<Arguments>参数集
<Argument name="layoutRegion" value="background:#FDFEDA; border:1px #DBB74A solid; padding:4px; white-space:nowrap; overflow:visible" />参数名layoutRegion
</Arguments>
...
<HtmlContainer content="1) left"文本内容 layoutConstraint="left"停靠left style="${argument.layoutRegion}" />容器(类似div)参数使用方式${argument.layoutRegion}
3,锚定式布局
锚定式布局的基本思路就是设定控件的边界与容器或其它控件之间的距离。
锚定式布局不仅支持对left和top边的定位,还支持对right和bottom边的定位。
锚定式布局不仅可以将容器的边界作为锚定目标进行定位,还支持将其他控件的边界作为锚定目标进行定位。
锚定式布局不但支持以数值作为锚定值,也支持以百分比作为锚定值。
dialog1.show();显示弹出框
<Dialog id="dialog1" layout="Anchor"设置布局 caption="场景1"标题栏内容 contentOverflow="hidden"隐藏超出内容 height="300" maximizeable="true" width="600">定义弹出框
<Children>???
<HtmlContainer content="1) left:20; top:20" layoutConstraint="left:20; top:20" style="${argument.layoutRegion}"/>
</Children>
</Dialog>
layoutConstraint锚定布局取值
anchorLeft:previous对上一个元素左靠
anchorRight:previous对上一个元素右靠
anchorTop:previous对上一个元素顶靠
heightOffset: -40权重40%并减去40像素
4,视图拦截器
视图拦截器代码动态添加按钮,每个按钮还被指定了各自的布局条件、单击事件。
视图拦截器中的onReady方法自动注入参数。
<View listener="spring:dynaView#onViewInit" layout="padding:20" title="Dyna View">//listener对应java中的类和方法,监听初始化事件
<Panel id="panelButtons" layout="Anchor">
<Property name="height">200</Property>
<Property name="width">600</Property>
</Panel>
</View>
@Component
public class DynaView {
public void onViewInit(Panel panelButtons) {//无返回值,直接改变参数,变量是指针
panelButtons.setCaption("此标题是通过视图拦截器设置的");//Panel 容器setCaption设置标题
for (int i = 1; i <= 8; i++) {
Button button = new Button();//定义按钮
button.setCaption("Button " + i);//定义按钮名称
AnchorLayoutConstraint layoutConstraint = new AnchorLayoutConstraint();//定义锚定式布局
layoutConstraint.setAnchorLeft(AnchorMode.previous);
layoutConstraint.setLeft("5");
layoutConstraint.setTop("10");
button.setLayoutConstraint(layoutConstraint);//设置按钮布局属性layoutConstraint
button.addClientEventListener(//添加点击事件
"onClick",
new DefaultClientEvent(
"dorado.MessageBox.alert('You clicked ' + self.get('caption'));"));
panelButtons.addChild(button);
}
}
}
5,Ajax
可暴露服务
JavaScript中调用异步操作
Container部分布局容器View子节点
layout="hbox"
<AjaxAction id="toUpperCaseAction" parameter="Hello World!">
<ClientEvent name="onSuccess">dorado.MessageBox.alert(self.get("returnValue"));</ClientEvent>//returnValue返回值
<Property name="caption">转成大写</Property>按钮名称,属性名称caption
<Property name="service">#toUpperCase</Property>对应Ajax类的toUpperCase方法,属性名称service
</AjaxAction>
<Button action="toUpperCaseAction"/>定义的AjaxAction 标签id
//prompt函数参数text,defaultText,callback,
<AjaxAction id="multiplyAction">
<Property name="executingMessage">正在计算...</Property>
<Property name="service">#multiply</Property>
</AjaxAction>
<Button>
<ClientEvent name="onClick" signature="multiplyAction">dorado.MessageBox.prompt("请在这里输入任意两个乘数", {//标题栏文字
defaultText: "3*5",//可输入文本框
callback: function(text) {//回调函数
var nums = text.split("*");
var parameter = {
num1: nums[0],
num2: nums[1]
};
multiplyAction.set("parameter", parameter).execute(function(result) {
dorado.MessageBox.alert(nums[0] + " * " + nums[1] + " = " + result);
});
}
});
</ClientEvent>
<Property name="caption">Ajax乘法</Property>
</Button>
@Expose
public int multiply(int num1, int num2) {
return num1 * num2;
}
//捕获异常
<AjaxAction id="errorAction">定义errorAction
<ClientEvent name="onFailure">dorado.MessageBox.alert("我就知道一定会出错!\n错误原因:" + arg.error.message);
arg.processDefault = false;</ClientEvent>
<Property name="caption">捕获异常</Property>//点击事件
<Property name="service">#errorAction</Property>//映射方法
</AjaxAction>
<Button>
<Property name="action">errorAction</Property>//使用action
</Button>
@Expose
public void errorAction() {
System.out.println(100 / 0);
}
<Container layout="vbox align:left">
<AjaxAction id="getMemInfo">
<ClientEvent name="onSuccess" signature="self, arg, labelMemInfo, progressBarMemInfo, buttonGetMemInfo">labelMemInfo.set("text", "空闲内存: " + arg.result.freeMemory + " 总内存: " + arg.result.totalMemory);//labelMemInfo下面定义id为labelMemInfo的<label>
progressBarMemInfo.set({//下面定义的ProgressBar 滚动条id为progressBarMemInfo
maxValue: arg.result.totalMemory,//滚动条最大值
value: arg.result.totalMemory - arg.result.freeMemory//滚动条当前值
});
if (buttonGetMemInfo.get("toggled")) {
setTimeout(function(){
self.execute();//self表示ClientEvent
}, 800);//0.8秒执行一次ClientEvent
}
</ClientEvent>
<ClientEvent name="beforeExecute" signature="labelRetrievingMemInfo">labelRetrievingMemInfo.set("visible", true);</ClientEvent>//执行前
<ClientEvent name="onExecute" signature="labelRetrievingMemInfo">labelRetrievingMemInfo.set("visible", false);//设置visible属性值</ClientEvent>//执行后
<Property name="caption">提取Server端内存使用情况</Property>
<Property name="service">#getMemInfo</Property>
<Property name="modal">false</Property>
</AjaxAction>
<Button id="buttonGetMemInfo">
<Property name="action">getMemInfo</Property>
<Property name="toggleable">true</Property>
</Button>
<Container layout="hbox regionPadding:20">
<Property name="height">20</Property>
<Label id="labelMemInfo">
<Property name="text">------</Property>
</Label>
<Label id="labelRetrievingMemInfo">
<Property name="visible">false</Property>
<Property name="text">Retrieving</Property>
<Property name="style">
<Property name="fontWeight">bold</Property>
<Property name="color">green</Property>
</Property>
</Label>
</Container>
<ProgressBar id="progressBarMemInfo">
<Property name="width">300</Property>
</ProgressBar>
</Container>
如何点击之后改变buttonGetMemInfo.get("toggled")即按钮buttonGetMemInfo的toggled属性,猜测是button之后自动改变Button的toggled属性
6,javascript控制器
引入js文件
1)直接引用,view的子属性标签javaScriptFile,多个js,逗号分隔
<Property name="javaScriptFile"></Property>
相同目录下自动加载同名js
2)配置引用
packages-config.xml配置方式,在每一个项目的dorado-home文件夹下都有packages-config.xml配置文件
<config>
<Patterns>
<Pattern name="js" contentType="text/javascript" charset="UTF-8" mergeRequests='${configure["view.mergeJavaScript"]}' resourceSuffix=".js" />
<Pattern name="css" contentType="text/css" charset="UTF-8" mergeRequests='${configure["view.mergeStyleSheet"]}' resourceSuffix=".css" />
</Patterns>
<Packages>
<Package name="common" pattern="js"></Package>//所有View都加在common
//baseUri根路径
<Package name="syntax-highlighter-css" pattern="css" baseUri=">libraries/syntax-highlighter">
/libraries/syntax-highlighter/shCore,
/libraries/syntax-highlighter/shThemeDefault
</Package>
<Package name="syntax-highlighter" pattern="js" depends="jquery,syntax-highlighter-css">
/libraries/syntax-highlighter/jquery.beautyOfCode,
/libraries/syntax-highlighter/jquery.beautyOfCode.init,
/libraries/syntax-highlighter/shCore,
/libraries/syntax-highlighter/shBrushJava,
/libraries/syntax-highlighter/shBrushJScript,
/libraries/syntax-highlighter/shBrushXml
</Package>
</Packages>
</config>
//view中使用packages属性,用于引入packages-cinfig.xml中配置的资源包(name属性),如果有多个资源包,逗号分隔:
js绑定Xml方式
利用Javascript中的"Annotation"来完成事件的挂接
/** @Bind #buttonOK.onClick */按钮绑定点击事件
function buttonOK() {}
/** @Bind ^readOnlyEditor.onCreate */批量绑定事件 button子标签属性<Property name="tags">readOnlyEditor</Property>
function setReadOnly(self) {}
以支持EL表达式
alert("${request.getRequestURI()}");
匿名事件
/** @Bind #buttonOK.onClick */
!function() {
alert("buttonOK Clicked.");
}
声明式公用方法
@View和@Global区别
@View用于标注某个方法在View中可见,@Global用于标注某个方法全局可见。
/** @View */
function showMessage(text) {
dorado.MessageBox.alert(text);
}
我们可以在其他地方(包括view.xml中或其他js文件中)通过 view.showMessage() 来调用它了
@Global的作用的是把方法标注成全局方法,我们可以在其他地方直接通过 showMessage() 来调用它。
出现多个View实例
强烈推荐首先考虑使用@View,@View可以在几乎所有场景下替代@Global。
7,单表数据维护
如何配置基本的DataType?
使用Annotation快速的定义DataProvider和DataResolver。
DataSet的概念以及DataSet如何通过DataProvider获得数据。
数据绑定控件的基本使用方法。
数据提交(即UpdateAction)的基本使用方法。
初步了解Dorado提供的HibernateDAO。
<Model>//定义表格数据类型(列结构)
<DataType name="ProductType" parent="Bean" meta="x:75;y:45">//定义ProductType表格显示的数据列
<Property name="creationType">com.bstek.dorado.sample.entity.Product</Property>//自动导入实体类的属性作为PropertyDef
<Property name="autoCreatePropertyDefs">true</Property>//开启自动创建PropertyDef
<PropertyDef name="id" readOnly="true"/>//添加PropertyDef
<PropertyDef name="productName" required="true"/>
</DataType>
</Model>
<View title="Product Maintain">
<Property name="packages">font-awesome</Property>
<DataSet id="dsProducts">//定义数据集
<Property name="dataProvider">#getAll</Property>
<Property name="dataType">[ProductType]</Property>
<Property name="pageSize">100</Property>
</DataSet>
<UpdateAction id="actionSave">//定义数据提交action调用java
<Property name="successMessage">保存成功!</Property>
<Property name="dataResolver">#saveAll</Property>//调用saveAll
<Property name="caption">Save</Property>//按钮文字
<Property name="iconClass">fa fa-save</Property>//小图标
<UpdateItem>//更新参数
<Property name="dataPath">!DIRTY_TREE</Property>//用于描述希望提交DataSet中哪些数据的数据路径
<Property name="dataSet">dsProducts</Property>//使用数据集
</UpdateItem>
</UpdateAction>
<ToolBar layoutConstraint="top">
<DataPilot>//分页
<Property name="ignored">false</Property>
<Property name="dataSet">dsProducts</Property>
<Property name="itemCodes">pages,|,pageSize,|,+,-,x</Property>
</DataPilot>
<Separator/>
<ToolBarButton>
<Property name="action">actionSave</Property>
</ToolBarButton>
</ToolBar>
<DataGrid>
<Property name="dataSet">dsProducts</Property>//表格
<Property name="scrollMode">viewport</Property>//滚动条
<IndicatorColumn/>
</DataGrid>
</View>
@Component
public class SimpleCRUD {
@Resource//自动注入实体类
private ProductDao productDao;
@DataProvider//定义DataProvider数据查询
public Collection<Product> getAll() throws Exception {
return productDao.getAll();//返回数据
}
@DataProvider
public void getAll(Page<Product> page) throws Exception {//带分页的返回数据
//page中包含:
//每页加载的数据是多少条
//page.getPageSize();
//需要加载的是第几页
//page.getPageNo();
//Dao层的分页查询方法
productDao.getAll(page);//再Dao中获取page中的查询条件,获取分页数据
page.setEntities(p.getResults());
page.setEntityCount(p.getTotalCount());
//处理后的数据要存放在Page对象中,参考前面的fundUsers方法,利用setEntities()方法存放数据,并利用setEntityCount()存放总的数据量信息,便于前台分页控件可以计算出一共有多少页。
}
@DataResolver//定义DataResolver数据保存
@Transactional
public void saveAll(Collection<Product> products) {//处理数据
productDao.persistEntities(products);
}
}
//添加删除取消保存分页控件
DataPilot是数据导航条控件,主要用于数据分页导航显示等
在@DataProvider方法的参数中加Page<T> page对象自动注入
8,主从表视图
SplitPanel 主要作用是通过分隔栏将页面上的空间分为两块,继承Control控件, SplitPanel的direction属性设置(上下左右)默认左右,支持局部区域最小化缩进,position设置位置大小,子标签MainControl主组件,SideControl
Container继承Control控件,是一个容器控件
DataType 的属性
meta="child:Product" 被Product继承
parent="BaseProduct" 继承BaseProduct
9,懒装载
<DataType name="Category" parent="global:Category" meta="x:75;y:15">
<PropertyDef name="products"/>
</DataType>
<DataGrid dataSet="dsCategories">
<Property name="selectionMode">none</Property>
<IndicatorColumn/>
</DataGrid>
<PropertyDef name="products"/>
替换为
<Reference name="products">
<Property name="dataProvider">productInterceptor#getProductsByCategoryId</Property>
<Property name="parameter">$${this.id}</Property>
</Reference>
可以在DataGrid中使用以下方式来获得数据表。
<DataGrid>
<Property name="dataPath">#.products</Property>
<Property name="dataSet">dsCategories</Property>
<IndicatorColumn/>
</DataGrid>
每点击DataGrid dsCategories一行数据,重新获取一次DataGrid products的数据
10,MapValue映射
实现改写表的一列数据,将对应显示值通过一一映射改写(ajax方式)
<DataType name="Employee" parent="global:Employee">
<PropertyDef name="titleOfCourtesy">
<Property name="mapping">
<Property name="mapValues">${dorado.getDataProvider("employeeInterceptor#getTitlesOfCourtesy").getResult()}</Property>
</Property>
</PropertyDef>
</DataType>
@DataProvider
public Map<String, String> getTitlesOfCourtesy() {
Map<String, String> mapValue = new LinkedHashMap<String, String>();
mapValue.put("Mr.", "Mister");
mapValue.put("Mrs.", "Mistress");
mapValue.put("Ms.", "Miss");
mapValue.put("Dr.", "Doctor");
return mapValue;
}
<DataColumn>方式修改显示的字段样式
<ClientEvent name="onRenderCell">//
$(arg.dom).empty();
var status=arg.data.get("status");
if(status=="失败"){
arg.dom.innerHTML="<strong><font color='red'>失败</font></strong>";
}
</ClientEvent>
11,递归树
动态生成的可打开式菜单
//categories:是一个CategoryNode组合的数组对象,其数据来自"main#getCategories";
//examples:是一个BaseExample组合的数组对象,其数据来自"main#getExamplesByCategoryId";
//$${this.id}以当前CategoryNode的id属性作为两个reference的dataProvider调用时的参数传入。
<DataType name="CategoryNode" parent="BaseExampleCategory">
<Reference name="categories" dataType="[CategoryNode]" dataProvider="main#getCategories" parameter="$${this.id}" />
<Reference name="examples" dataType="[BaseExample]" dataProvider="main#getExamplesByCategoryId" parameter="$${this.id}" />
</DataType>
<DataSet id="dsCategories" dataType="[CategoryNode]" dataProvider="main#getCategories" />
//treeExamples绑定了dsCategories对象,并通过BindingConfig定义节点属性。
<DataTree id="treeExamples" dataSet="dsCategories" width="300" height="400">
<BindingConfigs>
<BindingConfig childrenProperty="categories" labelProperty="label" recursive="true" icon=">images/folder.gif">
<BindingConfig childrenProperty="examples" labelProperty="label" icon=">images/file.gif" />
</BindingConfig>
</BindingConfigs>
</DataTree>
//childrenProperty="categories"表示子节点通过CategoryNode的categories获取
//labelProperty表示树节点初始化时,默认以树节点所绑定对象的哪个属性(本例为label)作为节点标题显示。
//recursive属性是用来定义是否一个递归的BindingConfig,如果递归则内部会继续按照如下的规则加载树节点
12,虚拟属性下拉选择
DataSetDropDown
//编辑框中的值作为参数filterValue传递到对应的DataProvider代码中
@DataProvider
public Collection<Product> getProducts(Map<String, Object> parameter) {
String productName = (String)parameter.get("filterValue");//注意参数名为filterValue
return productDao.find("from Product where category.productName ='" + productName + "'");
}
onSetFilterParameter//通过该事件自定义filterValue的值:
//@Bind #dataSetDropDown.onSetFilterParameter
!function(self, arg) {
arg.filterValue = "自定义的值";
}
//甚至直接动态的设置DataSetDropDown所绑定DataSet的其他参数值:
//@Bind #dataSetDropDown.onSetFilterParameter
!function(self, arg) {
arg.dataSet.set("parameter",{
categoryId:1,
deptId:"SH001"
});
}
filterOnTyping = false 模糊搜索 默认关闭
reloadDataOnOpen 是否在打开下拉框时重新加载(上下联动)
useDataBinding true下拉框与DataSet之间建立数据绑定,onFilterItem不会触发,数据过滤动作也将交由DataSet来
false 则一次性读取下拉数据,之后与DataSet不再产生关系,并且后续的数据过滤等操作也将与dorado.widget.ListDropDown的实现方式一致。
ListDropDown
items属性定义下拉框的数据
1利用逗号分割符定义,2利用IDE的向导工具定义,3利用JSON定义,4通过DataProvider提供数据
通过displayProperty定义下拉数据默认显示对象中那个属性。
望以表格的形式展现多个属性的时候,就需要利用ListDropDown的DataColumn子元素
DataColumn通过property与对应的下拉框行数据对象的某一个属性绑定:
Trigger与编辑框相关联的事件触发器。
onExecute事件我们可以定义上图按钮图标的单击事件
AutoForm是一种自动表单,是AutoFormElement的一个集合,内部可以定义多个AutoFormElement
<AutoForm cols="*" dataSet="dsOrders">
表单文本框
<AutoFormElement>
<Property name="property">shipCity</Property>
</AutoFormElement>
表单下拉框
<DataSetDropDown id="ddEmployees" dynaFilter="true">
<Property name="dataSet">dsEmployees</Property>
<Property name="autoOpen">true</Property>
<Property name="assignmentMap">employeeId=id,employeeName=firstName</Property>
<Property name="displayProperty">firstName</Property>
</DataSetDropDown>
...
<AutoFormElement>
<Property name="property">employeeName</Property>
<Property name="trigger">ddEmployees</Property>
<Editor/>
</AutoFormElement>
表单时间
<AutoFormElement property="orderDate">
<Editor>
<DateTimeSpinner>
<Property name="type">date</Property>
<Property name="trigger">defaultDateDropDown</Property>
</DateTimeSpinner>
</Editor>
</AutoFormElement>
表单不可操作文本
<AutoFormElement>
<Property name="property">employeeId</Property>
<Property name="readOnly">true</Property>
</AutoFormElement>
13,简单查询 1
AutoForm表单数据
AutoForm对象formCondition,如果我们直接通过.get("entity")方法,会自动返回给我们一个JSON对象。我们将这个 JSON对象直接赋值给dsOrders的parameter参数,并调用dsOrders的flushAsync激活Java服务层定义好的query 方法,执行查询。
dsOrders.set("parameter", formCondition.get("entity")).flushAsync();