如何创建Cocoon CForm
Introduction
Introduction
Cocoon has an advanced forms framework. Together with Flow and JXTemplates, Cocoon Forms (or CForms) provides a solid basis for building interactive web applications. Cocoon Forms handles complex use cases while still being simple enough to be used by non-Java-programmers who want to add forms to their site.
To create a form with CForms you need to define two things:
- the form model
- the form template
The form model is defined by a form definition. This is an XML file describing the structure of the form, by declaring the widgets it consists of. This file doesn't contain any presentational information. Based on the form definition, a form instance can be created. This is a specific instance of the form that will hold actual data. The form defintion is to the form instance what a Java class is to a Java object, or what an XML Schema is to an XML document.
Since the form definition is simply described in an XML file, this means you can create forms without any knowledge of Java. Unlike some other form frameworks, you don't need to write Java classes to hold form data.
As stated before, a form consists of a number of widgets. A widget is an object that knows how to read its state from a Request object, how to validate itself, and can generate an XML representation of itself. A widget can remember its state itself, so unlike e.g. Struts, you do not have to write a form bean for that purpose. A widget can hold strongly typed data. For example, you can indicate that a field should contain a date. If you do this, you can be assured that after the form is successfully validated, and you retrieve its value, you will get a Date object. So your own business logic doesn't need to care about converting strings to other types, and all the locale and formatting related issues of this.
CForms contains a flexible set of widgets that should cover most needs. However like everything in CForms, you can add new ones of your own. One special widget is the repeater widget, which "repeats" a number of other widgets multiple times, as is needed to generate table-like structures. Widgets can thus have child widgets, so a form instance is effectively a widget tree.
The presentation of the form is (usually) handled by a form template. The form themplate is an XML file (e.g. an XHTML file, but this could be any markup) and on the places you want a widget to appear, you insert a special tag referencing that widget. After processing by the Forms Template Transformer, these tags will be replaced by the XML representation of the widget, which contains all state information of the widget (its value, validation errors, ...). These bits of XML can then be transformed to plain HTML by an XSLT. Note that this XSLT only has to know how to style certain kinds of widgets, but not individual widget instances itself. Thus one template in this XSLT can style all widgets of a certain type that appear on all forms you might have. Cocoon includes a flexible, configurable XSLT that covers most needs.
Below a typical scenario is described to explain how things fit together:
- Initially, the controller logic asks the FormManager component to create a form instance based on a form definition (form definitions are cached, so creating an instance is very fast).
- The controller can then optionally pre-populate this form object with some data. To fill the form with data from a bean or XML document, a binding framework is available.
- Then the form is shown by calling a pipeline.
- When the form is submitted, the controller will let the form instance object process the request, so that all widgets can read their value from the request. Some might generate events, which will be handled by event handlers. Validation of the widget tree is also triggered, whereby all widgets will validate themselves based on widget validators described in the form definition. The controller can afterwards perform application-specific validation logic.
- If there were validation errors, the form will be redisplayed. Otherwise the controller will decide what's the next step, for example saving the form data back to a bean or calling some backend process using data from the form.
Next step: have a look at a concrete sample to get a feel for how things work.
Errors and Improvements? If you see any errors or potential improvements in this document please help us: View, Edit or comment on the latest development version (registration required).
cocoon是在Tomcat下执行的,一个网页的生成要经过10来个管道处理,当使用到数据库查询时,采用AJAX技术只更新部分网页数据,不会整页更新,减少传输量,在这样的情形下,其表现已与静态网页相差无几.
多语言支持
这是Java i18n没错
但与一般的有些不同
Cocoon的内容是动态生成,页面上需要i18n的文字,是给他一个tag,在浏览时系统再按照使用者语系将内容一一填入,而一般是有完整不同的档案,系统只是类似转址而已.
其它Frame Work或者也有,但我才疏学浅,不清楚,我只是试着介绍Cocoon给大家
Cocoon目前最热的主题是CForm,一个CForm由下述组成:
1.form definition:定义Form有哪些字段,字段属性,字段检查...
2.form binding:定义form与DB或xml-DB对应关系
3.form template:定义字段在画面的表现.
4.Flow Script:用Java script定义Form的后台动作.
5.sitemap:定义系统接收URL时如何解析与分配工作.
在Cocoon中 使用者输入的URL是没有对应任何档案,所有前台数据一定动态生成.而sitemap是使用者完全碰不到的档案.
上述5个动作可以是由不同的人同时发展,所以Cocoon相当结构化,适合发展大型系统
只有上述5个还是不够的,还有一些较为系统级的,如database操作,前台画面的一些细节,但这些部分基本都组件化 可重复使用 所以在'量产'时 可以不管他
关于SOAP
Cocoon可以当成WEB-Service的主机与客户端,在demo中,财务有一实时汇率,就是读取远程主机汇率数据.
这使得Cocoon在SCM场合非常适用.
关于Portal
Cocoon有一个Portal,可以组织外部网页,或者内部Cform 或者JSR168 demo就是将内部CForm整合进来
Cocoon的整合能力
Cocoon使用Avalon Framework,只要适当指定,就可以将各种java的应用整合进来
关于AJAX
在任一画面中,查询DATABASE数据,或新增或删除一笔明细,只有影响到的字段数据会更新,这就是AJAX.
在Cocoon 2.1.8-dev的Cform中,这是预设能力,无须进行任何编码,只要指明AJAX=true即可
生成多种文件能力
大家可以在demo中业务的报表上生成一些PDF窗体
除此之外 Word Excel SVG PNG JPEG 甚至Midi都可以
Cocoon所用到的东西
所有的代码就只有JAVA JAVAScript XML 三种 够少了吧
但用起来千变万化
在使用Cocoon的人当中(加入Mail讨论者),以德国人最多,其余是欧洲各国,南非,澳洲等,中文书只有约3年前北京希望所出,那时的技术以XSP为主,现在的CForm基本上找不到中文数据.
维欣已研究Cocoon许久,现在稍有作品,现计划推广此技术,欢迎有兴趣的人参加,只要愿意加入的超过10人,我会开一个专栏一歩一歩介绍Cocoon.
Cocoon的分支
1.8.x 使用反应器结构,DOM解析XML,速度慢,新创XSP以及XSP Logicsheet 作为前台网页设计.
2.0.x 使用管道结构,SAX解析XML,速度较快,新创XForm作为前台网页数据输出入.
2.1.x 主要是新创CForm与Flow Script,使前台数据输入的设计更为完整.
目前最新版是2.1.7 在2.1.8-dev中又将CForm引进AJAX,之前设计的画面只要加入AJAX=true便可以有此功能
当然Cocoon还有很多功能,但我将把重点放在CForm上,慢慢介绍如何用Cocoon设计一个输出入的画面
CFORM 一个功能强大的网页窗体
CFORM的前身名为WOODY,以下内容翻译自Cocoon Woody范例 http://cocoon.apache.org/2.1/userdocs/forms/index.html 英文功力不好,看不懂请提问.
Introduction
Cocoon has an advanced form framework. It is simply called "Forms" or "Cocoon Forms", but mostly referred to as CForms. Previously it was called "Woody".
介绍
Cocoon有一个先进的窗体框架,名为Forms或Cocoon Forms,但大部分时候我们将称呼为CForm,以前的名字叫Woody
Combined with other Cocoon technologies, such as flowscript and the JXTemplate generator, this provides a solid basis for building webapplications in Cocoon.
与Cocoon其它技术相结合,如flowscript与JXTemplate产生器,构成Cocoon网页应用程序的基础
CForms aims to be powerful enough to handle complex use cases while still being simple enough to be used by non-Java-programmers who want to add a form to their site.
CForms的目标是提供一个简单的方法给非JAVA程序设计师完成一个复杂的网页窗体
Essentially to create a form with CForms you need to define two things:
。the form model
。the form template
要开发CForm网页,您必须定义:
。窗体模式
。窗体模板
The form model is defined by a form definition. This is an XML file describing the structure of the form, by declaring the widgets it consists of. This file doesn't contain any presentational information. Based on the form definition, a form instance can be created. This is a specific instance of the form that will hold actual data. The form defintion is to the form instance what a Java class is to a Java object, or what an XML Schema is to an XML document.
窗体模式就是窗体定义,这是一个XML格式的档案用来描述窗体的结构,内含窗体零件宣告,但不包含任何的画面表达信息,基于窗体定义,系统会产生一个窗体对象,此对象保存实际的数据,这关系就像由Java类生成对象或由XML大纲与XML文件一样
Since the form definition is simply described in an XML file, this means you can create forms without any knowledge of Java. Unlike some other form frameworks, you don't need to write Java classes to hold form data.
因为窗体定义是用XML格式,这就意味着您可以定义窗体而不需了解JAVA,与其它窗体框架不同,您不需要写JAVA类来保存数据
As stated before, a form consists of a number of widgets. A widget is an object that knows how to read its state from a Request object, how to validate itself, and can generate an XML representation of itself. A widget can remember its state itself, so unlike e.g. Struts, you do not have to write a form bean for that purpose. A widget can hold strongly typed data. For example, you can indicate that a field should contain a date. If you do this, you can be assured that after the form is successfully validated, and you retrieve its value, you will get a Date object. So your own business logic doesn't need to care about converting strings to other types, and all the locale and formatting related issues of this.
如前所述,一个窗体有许多小零件,小零件知道如何从请求对象读出自己的状态,如何检查自己的有效性,如何生成XML来代表自己,一个小零件可以记得自己的状态,这与Struts不同,您不需要因此写一个窗体bean.小零件可以保存窗体型态,例如您可以指定一个日期字段,只要如此设定,您可以确保由窗体传回的数据一定是日期格式,所以您的企业逻辑并不需要对此作任何数据转换,本地化,以及格式等等.
CForms contains a flexible set of widgets that should cover most needs. However like everything in CForms, you can add new ones of your own. One special widget is the repeater widget, which "repeats" a number of other widgets multiple times, as is needed to generate table-like structures. Widgets can thus have child widgets, so a form instance is effectively a widget tree.
CForms包含一组富有弹性的小零件,大部分网页应用都有涵盖,然而,就像CForms的每件事一样,您可以自行加入,一个特殊的小零件是重复器,重复器重复了其它小零件多次,这在表格结构是需要的,所以小零件可以有子零件,一个窗体就是一个小零件树.
The presentation of the form is (usually) handled by a form template. The form themplate is an XML file (e.g. an XHTML file, but this could be any markup) and on the places you want a widget to appear, you insert a special tag referencing that widget. After processing by the Forms Template Transformer, these tags will be replaced by the XML representation of the widget, which contains all state information of the widget (its value, validation errors, ...). These bits of XML can then be transformed to plain HTML by an XSLT. Note that this XSLT only has to know how to style certain kinds of widgets, but not individual widget instances itself. Thus one template in this XSLT can style all widgets of a certain type that appear on all forms you might have. Cocoon includes a flexible, configurable XSLT that covers most needs.
窗体的表现是由窗体模板所管理,窗体模板是一个XML格式档案,这里是小零件显示的地方,插入标记来引用小零件,在进行窗体模板转换之后,这些标记会以XML方式表现出所有小零件的值,有效性检查错误...等,这些XML数据使用XSLT转换成HTML,注意:这些XSLT只需要知道如何表现各种小零件的外观,而不是一个一个的个别处理,所以一个模板可以适用您所有的Form,Cocoon包含一个有弹性可修改的XSLT,可以处理大部分的需要.
.Initially, the controller logic asks the FormManager component to create a form instance based on a form definition (form definitions are cached, so creating an instance is very fast).
.一开始,控制器逻辑请求窗体管理部件以窗体定义为基础产生一个窗体对象(窗体定义会被缓存,所以产生对象的速度很快)
.The controller can then optionally pre-populate this form object with some data. To fill the form with data from a bean or XML document, a binding framework is available.
.控制器在发布前可以额外的放入一些数据.这些数据来自bean或XML档案,使用binding框架将数据放入.
.Then the form is shown by calling a pipeline.
.然后呼叫管道,画面显示.
.When the form is submitted, the controller will let the form instance object process the request, so that all widgets can read their value from the request. Some might generate events, which will be handled by event handlers. Validation of the widget tree is also triggered, whereby all widgets will validate themselves based on widget validators described in the form definition. The controller can afterwards perform application-specific validation logic.
.当窗体提交,控制器会让窗体对象处理请求,所有小零件都可以从请求读取自己的值,有些会产生事件,事件是由事件处理器处理,小零件树的有效性检查同时触发,所有的小零件都基于窗体定义自我检查有效性,控制器再检查整体有效性逻辑.
.If there were validation errors, the form will be redisplayed. Otherwise the controller will decide what's the next step, for example saving the form data back to a bean or calling some backend process using data from the form.
.如果有效性检查错误,画面会再一次显示,否则控制器会决定下一步骤,例如保存画面数据到bean,或呼叫一些后台程序处理数据.
Next step: have a look at a concrete sample to get a feel for how things work.
下一步骤:将演示实例来感受这是如何实现的.
Below a typical scenario is described to explain how things fit together:
A simple CForms example
In this example we will show how to create a simple registration form using CForms and flowscript. We will follow to following steps:
一個簡單的CForm例子
在此一簡單的例子,我們將展示如何使用CForm與flowscript建立一個註冊表單,我們將執行下列步驟
1.Create a form definition file
1.建立一個表單定義檔.
2.Create a template file for the Forms Template Transformer
2.建立一個模板檔案,用來做表單模板轉換
3.Write a bit of flowscript
3.寫一些flowscript
4.Add some pipelines to the sitemap
4.在sitemap加入一些管道
Here is a screenshot of the form we're going to create:
Create a form definition file
建立一個表單定義檔
Below the form definition file is displayed. This lists all the widgets in the form, together with their configuration information.
下面就是表單定義檔.包含所有此表單用到的小零件,以及設置的訊息.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
<fd:form xmlns:fd="http://apache.org/cocoon/forms/1.0#definition"> <fd:widgets> <fd:field id="name" required="true"> <fd:label>Name:</fd:label> <fd:datatype base="string"/> <fd:validation> <fd:length min="2"/> </fd:validation> </fd:field> <fd:field id="email" required="true"> <fd:label>Email address:</fd:label> <fd:datatype base="string"/> <fd:validation> <fd:email/> </fd:validation> </fd:field> <fd:field id="age"> <fd:label>Your age:</fd:label> <fd:datatype base="long"/> <fd:validation> <fd:range min="0" max="150"/> </fd:validation> </fd:field> <fd:field id="password" required="true"> <fd:label>Password:</fd:label> <fd:datatype base="string"/> <fd:validation> <fd:length min="5" max="20"/> </fd:validation> </fd:field> <fd:field id="confirmPassword" required="true"> <fd:label>Re-enter password:</fd:label> <fd:datatype base="string"/> <fd:validation> <fd:assert test="password = confirmPassword"> <fd:failmessage> The two passwords are not equal. </fd:failmessage> </fd:assert> </fd:validation> </fd:field> <fd:booleanfield id="spam"> <fd:label>Send me spam</fd:label> </fd:booleanfield> </fd:widgets> </fd:form> |
All elements are in the Forms Definition namespace: fd.
所有窗体定义文件的元素都有一个命名空间: fd.
Every definition file has a <fd:form> element as the root element.
所有定义档都使用<fd:form>元素作为根元素.
The child widgets of the form are defined inside the <fd:widgets> element. As you can see, most of the widgets are field widgets. The field widget is the most important widget in CForms. It is very flexible because it can be associated with different datatypes and with a selection list. See the reference docs for more information on this and other widgets.
窗体的小零件定义在<fd:widgets>元素内. 如您所见, 大部分小零件是字段零件. 字段零件是cforms最重要的零件. 它很有弹性因为它能使用多种不同的数据型态与选择列, 更多数据请看参考文件.
A nice feature is that the fd:label tags can contain mixed content. On the one hand, this can be used to provide rich formatting in the label. But it also enables you to put i18n-elements in there, to be interpreted by the I18nTransformer. This way, internationalisation is done using standard Cocoon techniques.
一个不错的特性是fd:label标记可以有混用的内容. 换句话说, 这使得标签可以有丰富的表现形式. 但是这里也可以让您放入国际化元素, 以便国际化转换器能解译. 这样, 标准Cocoon技术就可拥有国际化.
Create a template file for the Forms Template Transformer
建立一个模板档案,用来做窗体模板转换
Here's the template for our registration form example:
这是我们注册窗体例子的模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<html xmlns:ft="http://apache.org/cocoon/forms/1.0#template" xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"> <head> <title>Registration form</title> </head> <body> <h1>Registration</h1> <ft:form-template action="#{$continuation/id}.continue" method="POST"> <ft:widget-label id="name"/> <ft:widget id="name"/> <br/> <ft:widget-label id="email"/> <ft:widget id="email"/> <br/> <ft:widget-label id="age"/> <ft:widget id="age"/> <br/> <ft:widget-label id="password"/> <ft:widget id="password"> <fi:styling type="password"/> </ft:widget> <br/> <ft:widget-label id="confirmPassword"/> <ft:widget id="confirmPassword"> <fi:styling type="password"/> </ft:widget> <br/> <ft:widget id="spam"/> <ft:widget-label id="spam"/> <br/> <input type="submit"/> </ft:form-template> </body> </html> |
The CForms-specific elements here are in the "Forms Template" namespace: ft.
CForm规定的元素在窗体模板中命名空间是ft
The <ft:widget-label> tag will cause the label of a widget to be inserted at the location of the tag. The <ft:widget> tag will cause the XML representation of a widget to be inserted at the location of that tag. The inserted XML will be in the "Forms Instance" namespace: fi.
<ft:widget-label>标记将使小零件的卷标放在这里. <ft:widget>标记会使小零件的XML表示方式放在这里. 插入的XML会有窗体事件命名空间: fi.
The XML representation of the widget will then be translated to HTML by an XSLT stylesheet (forms-samples-styling.xsl in our case -- see sitemap snippets below). This XSLT only has to handle individual widgets, and not the page as a whole, and is thus not specific for one form but can be reused across forms.
小零件的XML表达方式将会使用XSLT样式表转为HTML格式(在我们的例子是forms-samples-styling.xsl -- 请看下面sitemap片段). 此XSLT只处理单独的小零件, 而不是整个画面, 所以它并不是为单一窗体特制的, 可以在所有的窗体里重复使用.
For certain widgets it may be necessary to provide extra presentation hints, such as the width of a text box, the style of a selection list (drop down, radio buttons, ...) or class and style attribute values. This can be done by putting a fi:styling element inside the ft:widget element. This element is in the fi namespace because it will be copied literally. The attributes and/or content of the fi:styling element depend on what is supported by the particular stylesheet used.
一些小零件可能需要额外的表现方式, 如文字输入的宽度, 选择列的样式(下拉, 选择按钮,...)或类与样式属性值. 这可以在ft:widget元素内用fi:styling元素来完成.这元素是在 fi 的命名空间,因为它是逐字拷贝过去的. fi:styling 元素的属性与内容是依其所使用的样式表而有所不同.
As an alternative to the template approach, you could also use the FormsGenerator, which will generate an XML representation of the whole form, and style that with a custom-written XSLT. For most users we recommend the template approach though.
另一种非模板方式, 您也可以使用窗体产生器, 这将产生整个窗体的XML格式, 与一个客制样式的XSLT. 我们对大部分使用者还是建议使用模板.
Write a bit of flowscript
寫一些flowscript
Flowscript is Cocoon's solution to handling the flow of a web interaction. It is based on the concept of continuations. If you don't know yet about continuations and flowscript, learn about it here.
Flowscript 是Cocoon處理網頁互動的解決方案. 這是基於連續性的觀念. 如您還不了解連續性與flowscript, 從這裡開始吧(這一篇未翻譯).
Here's the flowscript for our example, registration.js:
這是我們例子的flowscript, registration.js:
1
2
3
4
5
6
7
8
9
10
11
|
cocoon.load("resource://org/apache/cocoon/forms/flow/javascript/Form.js"); function registration() { var form = new Form("forms/registration.xml"); form.showForm("registration-display-pipeline"); var model = form.getModel(); var bizdata = { "username" : model.name } cocoon.sendPage("registration-success-pipeline", bizdata); } |
The flowscript works as follows:
flowscript的工作如下:
First we create a Form object, specifying the form definition file to be used. The Form object is actually a javascript wrapper around the "real" Java form instance object.
首先建立一個表單物件, 指出使用哪個表單定義檔. 此Form物件實際上是JAVA表單物件採用javascript包裝.
Then the showForm function is called on the form object. This will (re)display the form to the user until validation of the form succeeded. As parameter to the showForm function, we pass the sitemap pipeline to be used to display the form.
然後呼叫表單物件的showForm函數. 這將不斷的重複顯示表單直到有效性檢查通過為止. 我們將sitemap的管道當作showform函數的參數.
Finally we get some data from the form (the entered name), and call a sitemap pipeline to display this data. This pipeline is based on the JXTemplate generator.
最後我們從表單取得一些資料(輸入的名字), 然後呼叫sitemap管道顯示資料. 這管道是基於JXTemplate產生器.
Add some pipelines to the sitemap
在sitemap加入一些管道
First of all, do not forget to register the registration.js file in the map:flow section of the sitemap, as follows:
首先,不要忘了在sitemap中map:flow節註冊registration.js檔,如下:
1
2
3
|
<map:flow language="javascript"> <map:script src="flow/registration.js"/> </map:flow> |
And here are the pipelines we need:
還有這些管道:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<map:match pattern="registration"> <map:call function="registration"/> </map:match> <map:match pattern="*.continue"> <map:call continuation="{1}"/> </map:match> <map:match pattern="registration-display-pipeline"> <map:generate src="forms/registration_template.xml"/> <map:transform type="forms"/> <map:transform type="i18n"> <map:parameter name="locale" value="en-US"/> </map:transform> <map:transform src="resources/forms-samples-styling.xsl"/> <map:serialize/> </map:match> <map:match pattern="registration-success-pipeline"> <map:generate type="jx" src="forms/registration_success.jx"/> <map:serialize/> </map:match> |
The first two are for managing the flowscript: when someone hits the registration URL, we call the registration function in our flowscript.
前二行是管理flowscript: 當有人進入這個註冊的網址, 我們在flowscript呼叫註冊函數
When a form is submitted, it will be matched by the second matcher, *.continue, which will continue the execution of the flowscript.
當表單提交, 將會符合第二個匹配器, *.continue, 這將繼續執行flowscript.
The third matcher is for displaying the form, and uses the Forms Template Transformer.
第三的匹配器用來顯示表單, 使用表單模板轉換器.
The fourth pipeline is for showing the "success" page using the JXTemplate generator, here is the contents of the registration_succcess.jx page:
第四個匹配器用來顯示"success"頁,用JXTemplate產生器, 這是registration_success.jx 的內容:
1
2
3
4
5
6
7
8
|
<html> <head> <title>Registration successful</title> </head> <body> Registration was successful for ${username}! </body> </html> |
Next steps
下一歩
The example we've studied here is quite simple. To have a feel for the power of CForms, take a look at the examples included included in the Forms block.
我們學的這例子很簡單. 要感受CForms的威力, 請到cocoon範例Forms block.
Cocoon Forms: field widget
Cocoon 表單: 欄位小零件
.Concept
.Datatypes
.Selection lists
.Conclusion
.Configuration
.概念
.資料型態
.選擇列
.結論
.組態
Concept
概念
The field widget is the most common widget. It is used both for text boxes or selection lists. It can be associated with different datatypes such as string, long or date to ask for different types of data.
欄位小零件是最常用的小零件. 用於文字輸入方塊或選擇列. 可運用在不同的資料型態如字串, 長整數, 或日期 的資料輸入上
Datatypes
資料型態
A datatype represents a certain type of data, such as a string, integer, decimal or date. Each datatype matches to a certain Java class. If you associate a field widget with a datatype, its setValue(Object) and getValue() methods will take, respectively return objects that are instances of that Java class (or subclasses thereof).
資料型態代表某種資料的型態, 如字串, 整數, 浮點數 或日期. 每個資料型態對應一種JAVA類. 如果您將一個指定一個資料型態給欄位小零件, 它的設值與取值函數將分別地返回這個JAVA類(或其子類)所生成的物件.
Each datatype is associated with a convertor. The task of the convertor is to convert from string representation to object representation, and vice versa.
每個資料型態有自己的變換器. 變換器的工作是將字串變換成物件, 等等.
The string to object conversion usually happens when converting the value entered by the user to an object. This process can fail if the user entered an incorrect string, for example abc when a number is required. In this case an appropriate validation error will be set on the widget. String to object conversion also happens when parsing data in selection lists (if the selection list is retrieved as XML) and can also be used as part of the binding.
字串-物件變換通常發生在變換使用者輸入的資料為物件. 如果使用者輸入錯誤的字串, 將會發生錯誤, 例如當需要數字卻輸入abc時.適當的有效性檢查錯誤將設給小零件. 當從選擇列分析資料時, 字串-物件變換也會發生(如果選擇列將整理成XML) 而且也將成為binding的一部份.
The object to string conversion happens when the state of the widget is spit out as XML, this is mostly when injecting the widget XML in the publishing pipeline.
物件-字串變換發生在小零件的狀態以XML格式輸出時, 大部分是發布網頁pipeline時注入的小零件XML.
By having a field widget associated with a datatype, you can be sure that, after successful validation of the widget, retrieving the value of the widget will give you an object of the correct type.
在欄位小零件中使用資料型態, 您可以確認當小零件有效性檢查成功, 從小零件取回的值是正確的型態.
The available datatypes and their respective convertors are documented in a separate document.
可用的資料型態與其所有的變換緝另文介紹.
Selection lists
選擇列
A field widget can furthermore be associated with a selection list. This makes that the field widget could be rendered either as a textbox or a list, depending on whether its datatype has a selection list. The selection list is related with the datatype: the values in the selection list should be of the same type as the datatype.
欄位小零件還可以進一步使用於選擇列. 這將使欄位小零件以文字方塊或列來顯示, 這要依據他的資料型態是否有選擇列而定, 選擇列與資料型態有關, 選擇列的值必須是相同的資料型態.
Selection list data can be specified directly in the form definition (for short, unchanging lists), retrieved from external sources (i.e. a Cocoon pipeline), or pulled from an oject structure. Full details on selection lists are also in a separate document.
選擇列的資料可以直接在畫面定義檔設定(適用在少資料且不會變更的場合), 從外部來源取得(Cocoon管道), 或者從物件架構取得, 關於選擇列的詳細資料在其他的文件.
Conclusion
結語
If we wouldn't make these datatype and selection list associations, we would need to create specific widgets for each possible combination: StringField, LongField, DateField, StringSelectionList, LongSelectionList, ...
如果我們不在選擇列使用資料型態, 我們就必須為每個可能的組合設計小零件: 字串欄位, 長整數欄位, 日期欄位, 字串選擇列, 長整數選擇列, ...
Configuration
配置
Configuration example:
配置例:
1 |
<fd:field id="..." required="true|false"> <fd:label>...</fd:label> <fd:hint>...</fd:hint> <fd:help>...</fd:help> <fd:datatype base="..."> [...] </fd:datatype> <fd:selection-list .../> <fd:validation> [...] </fd:validation> <fd:on-value-changed> [...] </fd:on-value-changed> </fd:field> |
The field element takes a required id attribute. This id should be unique among all widgets in the same container (i.e. inside the same fd:widgets element).
字段元素一须有一id属性, id必须在整个容器内是唯一的(意即: 在相同的fd:widgets元素之内).
The required attribute is optional, by default it is false. It indicates whether this field is required. This is a static property of the widget. If you want the field to be "conditionally required", then set this to false and use custom validation logic to check the requiredness of the field.
必须属性是额外的, 预设是不用, 意思是这字段是否必须. 这是静态属性. 如您想要字段是"看状态是否需要", 那么将此属性设为不需要, 然后用自定有效性逻辑检查此字段是否必须.
The fd:label element contains the label for this widget. This element is optional. It can contain mixed content. For internationalised labels, use i18n-tags in combination with Cocoon's I18nTransformer.
fd:label元素包含此小零件的卷标. 此元素是额外的. 它可以包含混和内容. 如要用国际化卷标, 使用国际化标记(i18n-tags), 并使用cocoon国际化转换器.
The fd:hint element contains a hint for the form control of this widget. This element is optional. It can contain a hint about the input control. For internationalised labels, use i18n-tags in combination with Cocoon's I18nTransformer.
fd:hint元素包含此小零件的窗体控制的暗示. 此元素是额外的. 它可以包含输入控制的暗示. 如要用国际化卷标, 使用国际化标记(i18n-tags), 并使用cocoon国际化转换器.
The fd:help element contains more help for the form control of this widget. This element is optional. It can contain text help about the input control. For internationalised labels, use i18n-tags in combination with Cocoon's I18nTransformer.
fd:help元素包含此小零件的窗体控制更多的帮助. 此元素是额外的. 它可以包含输入控制的帮助. 如要用国际化卷标, 使用国际化标记(i18n-tags), 并使用cocoon国际化转换器.
The fd:datatype element indicates the datatype for this field. This element is required. The base attribute specifies on which built-in type this datatype should be based. The contents of the fd:datatype element can contain further configuration information for the datatype. The possible datatypes and their configuration options are described over here.
fd:datatype元素指出此字段的数据型态. 此元素是必须的. fd:datatype的内容可以包含更多的数据型态配置讯息. 可能的数据型态与其配置选项在此描述.
The fd:selection-list element is used to associate a selection list with this field. See Datatypes for more details.
fd:selection-list元素用来指明此字段是使用选择列. 看数据型态来了解更多.
The fd:validation element specifies widget validators. See Validation for more details.
fd:validation元素设定小零件的有效性检查. 看有效性检查了解更多.
The fd:on-value-changed element specifies event handlers to be executed in case the value of this field changes. See also Event Handling. The interface to be implemented for Java event listeners is org.apache.cocoon.forms.event.ValueChangedListener. The WidgetEvent subclass is org.apache.cocoon.forms.event.ValueChangedEvent.
fd:on-value-changed元素设定了字段值变更时的事件处理. 请看事件处理章节. 实现的JAVA事件listener是org.apache.cocoon.forms.event.ValueChangedListener. 小零件事件的子类是 org.apache.cocoon.forms.event.ValueChangedEvent.
Note: Events used in <fd:on-value-changed> require that the form instance is stored serverside (because otherwise CForms doesn't know what the previous values of the fields were). This is automatically the case when you use flowscript. If you don't use flowscript you could store the form instance in e.g. the session.
注意: fd:on-value-changed使用的事件必须窗体实例储存在主机端(如不这样CForms无法知道此字段的前一次的值是什么). 当您使用flowscript时这是自动的. 如不使用flowscript您必须将窗体实例存在session.
有一个Cocoon最特别的架构Pipeline(不知其它有没有,先声明,免的又被吐嘈),是一个相当先进的做法.
Pipeline的用意是分层负责, 在XML中指定某个用途的namespace, 写好用到的tag, 然后在Pipeline中指定处理它的处理器, 这样就可以了.
所以Cform有Cform的处理器, i18n有i18n的....
这样做的好处是可以增加功能, 例如: 假设原先汇率来自数据库, 后来想改为从网络Webservice读取, 只要在当中插入SOAP的处理即可, 例如原先是使用XML File储存使用者数据, 将来源改为数据库就可使用数据库, 改为LDAP就可使用LDAP, 程序逻辑几乎没变.
当中间层的程序有变化时, 基本上应用程序都不需改变.
Cocoon Forms: multivaluefield widget
Cocoon窗体: 多值字段小零件
* Concept
* Configuration
* 概念
* 配置
Concept
概念
The fd:multivaluefield is similar to the field widget but can take multiple values. Its purpose is to handle those (HTML) form controls which submit their multiple values as multiple (HTTP) request parameters with the same name. A multivaluefield should always have an fd:datatype element combined with a fd:selection-list, since the user will have to select values from this list.
fd:multivaluefield 与字段小零件类似但可以取的多值. 它的目的是处理窗体控件在提交时使用单一名称传回多值. 一个多值字段必须有一个fd:datatype元素结合fs:selection-list, 因为使用者须从此列选择值.
The fd:multivaluefield could be rendered as a list of checkboxes or as a listbox in which the user can select multiple items. The CForms stylesheets also include a styling option to render them as a "double list", i.e. a list of available and selected values.
fd:multivaluefield 可被转换成一组检查方块或一个列方块给使用者选择多个项目. CForm 的样式表也包含了样式选项来将其转换成双列, 意即有二列, 一列是可选的值另一列是已选的值.
The setValue and getValue methods of the multivaluefield take respectively return arrays of objects (i.e. Object[]). The type of the objects in these arrays should match the datatype declared for the widget.
多值字段的设值与取值方法将返回一个对象数组(Object[]). 再数组中的对象型态必须与小零件宣告的数据型态相符.
Configuration
配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<fd:multivaluefield id="..."> <fd:label>...</fd:label> <fd:help>...</fd:help> <fd:hint>...</fd:hint> <fd:datatype base="..."> [...] </fd:datatype> <fd:selection-list> [...] </fd:selection-list> <fd:validation> [...] </fd:validation> <fd:on-value-changed> [...] </fd:on-value-changed> </fd:multivaluefield> |
Most of the elements and attributes have the same meaning as for the field widget.
大部分的元素與屬性與欄位小零件的是相同的.
Note: A multivaluefield cannot have a required attribute, instead you should use the value-count validator to check the number of values the user has selected.
注意: 一個多值欄位小零件不可以有必須屬性, 您必須使用數值數量的有效性檢查使用者選擇的數量.
Cocoon Forms: booleanfield widget
Cocoon 表單: 真假值欄位小零件
* Concept
* Configuration
* 概念
* 配置
Concept
概念
An fd:booleanfield is a field that has a value of true or false. Usually is rendered as a checkbox.
真假值欄位是一種只有真值或假值的欄位. 經常轉換成檢查方塊.
It is different from a field widget with a boolean datatype because an HTML checkbox submits no request parameter if the checkbox is unchecked. If you would render it instead as a listbox with true and false values, you could also use a regular field widget. Since the styling preference might change over time, it is however better to use consistently the fd:booleanfield widget.
這與欄位小零件有真假值的資料型態不同 因為HTML的檢查方塊沒有被選取時是沒有參數傳回的. 如您想用真假值取代列方塊, 您也可以用標準的欄位小零件. 因為預設的樣式可能改變, 所以最好還是用fd:booleanfield小零件.
A booleanfield cannot be marked as "required", because it is always required. It is either true or false. If you want tripples (true/false/none), use a normal field widget with a selection list.
真假值欄位不可以標示為必須, 因為它是一定需要的. 不是真就是假. 如您要用三個值(真/假/沒有), 用帶有選擇列的一般欄位小零件.
Configuration
配置
1
2
3
4
5
6
7
8
|
<fd:booleanfield id="...">
<fd:label>...</fd:label>
<fd:help>...</fd:help>
<fd:hint>...</fd:hint>
<fd:on-value-changed> [...]
</fd:on-value-changed>
</fd:booleanfield>
|
See field wiget for a description of the configuration options.
配置選項請看欄位小零件