Chapter 4: Form Widgets

什么是Form?

OFBiz中的Form不像我们理解的那样,必须有好几行好几列

这个是form


这个也是form

Form的使用

  1. form不可以直接访问及使用,必须要include进screen中才能使用
  2. 定义:我们一般把form的定义单独写在一个xml文件中,放在widgets这个目录下,如LearningForms.xml,一个简单的定义如下:
    <form name="FirstForm" type="single" target="processFirstForm">
    		<field name="firstName"><text/></field>
    		<field name="lastName"><text/></field>
    		<field name="submit"><submit/></field>
    	</form>

    其中,
    <form name="FirstForm" type="single" target="processFirstForm">

    定义了form的名字,类型,以及如果form中的按钮(如submit)按下以后会发送什么样的request
    <field name="firstName"><text/></field>
    <field name="lastName"><text/></field>
    <field name="submit"><submit/></field>

    field选项定义了这个form有多少个属性,后面的<text><submit>则是说明这个属性到底是什么类型的,需要输入呢?还是是按钮可以按
    OFBiz有个很贴心的地方,他会自动为我们的各个属性加入对应的标签,如图

    我并没有在form添加label,但它自动生成了label,每个label的内容正是field标签中的name,但是又有一点变化,它使用驼峰原则,并且将单词分开,首字母大写。
    当然,如果你想自己指定显示的名称,加上title属性即可
  3. 使用
    在screen中添加form的方法很简单,使用<include form>即可
    <screen name="OneFormScreen">
    		<section>
    			<widgets>
    				<decorator-screen name="xhtml-decorator">
    					<decorator-section name="title">
    						<label text="A Screen with just 1 form."/>
    					</decorator-section>
    					<decorator-section name="body">
    						<include-form name="FirstForm" location="component://learning/widget/learning/LearningForms.xml"/>						
    					</decorator-section>
    				</decorator-screen>
    			</widgets>
    		</section>
    	</screen>

Form的事件处理

<form name="FirstForm" type="single" target="processFirstForm">
		<field name="firstName"><text/></field>
		<field name="lastName"><text/></field>
		<field name="submit"><submit/></field>
	</form>

当form的submit按钮按下时候,会触发一个request,这个request的名字是有规律的:一般来说是process+list的名字(见name标签)。当然,你也可以设置target这个标签,这个标签规定了按下了form的按钮后会触发什么样的request
既然发送了request,我们肯定要在controller.xml中写相应的<request-map>来进行监听。
一般来说,按下按钮以后常常是需要对表中的数据进行一定处理(正如同form定义中的target这个标签,我们需要process form),而不是直接返回一个view。我们常常会定一个event来处理这些处理事件,所以<request-map>的完整版这样写

	<request-map uri="processFirstForm">
		<event type="java" path="org.ofbiz.learning.learning.LearningEvents" invoke="processFirstForm"/>
		<response name="success" type="view" value="OneFormScreen"/>
	</request-map>

下面来解读event这一行:
type - 说明这个event是什么类型的,常用的有java的,还有minilang的
path - 说明event文件在哪里,对于java来说,就是在那个包中
invoke - 调用这个event文件中的具体哪一个方法
我的简单理解,event就相当于对java类中一个方法的调用。

那么,这个java文件到底是什么样的呢?

package org.ofbiz.learning.learning;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.ofbiz.base.util.UtilHttp;
public class LearningEvents {
	public static String processFirstForm(HttpServletRequest request,  
			  HttpServletResponse response){
			String firstName = request.getParameter("firstName");
			String lastName = request.getParameter("lastName");
			request.setAttribute("combined", firstName + " " + lastName);
			request.setAttribute("allParams", UtilHttp.getParameterMap(request));
			request.setAttribute("submit", "Submitted");
			return "success";
	}
}

需要注意的是,被调用的方法,一定要是static的,这样就不必要实例化一个类了

那么,这个方法是如何知道用户输入了什么?又如何输出计算处理后的结果呢?

很好理解,使用request.getParameter可以得到用户输入的信息。
request.getParameter("firstName")对应<field name="firstName"><text/></field>的信息
request.getParameter("lastName")对应<field name="lastName"><text/></field>的信息
同样,使用setAttribute()方法,我们可以把event中计算的结果返回给screen使用,我们在screen中,可以这样得到event中处理的结果:

<container><label text="firstName: ${parameters.firstName}"/>  
</container>
<container><label text="lastName: ${parameters.lastName}"/> 
</container>
<container><label text="combined: ${parameters.combined}"/> 
</container>
<container><label text="submit: ${parameters.submit}"/></container>
<container><label text="All the parameters we received:"/> 
</container>
<container><label text="${parameters.allParams}"/></container>

Form的类型及详解

single类型

Single类型的Form最简单,只能有一个Record,只有一组数据

<form name="FirstForm" type="single" target="processFirstForm1">
		<field name="firstName"><text/></field>
		<field name="lastName"><text/></field>
		<field name="submit"><submit/></field>
	</form>


list类型

List类型的Form就是我们日常用的form,有表头,可以有很多行

	<form name="ListForm" type="list" list-name="listOfRecords" 
      		target="processListForm" separate-columns="true">
		<field name="firstName"><text/></field>
		<field name="lastName"><text/></field>
		<field name="submit"><submit/></field>
	</form>


从上图可以看出,list类型的form实际上是由很多个single类型的form组成的。
看表的定义,与single相比,多了list-name和separate-columns这两个属性。
我们先看separate-columns这个属性,为true的时候效果如上图,如果为false呢?


可以看到三个属性名全部连在一起放在一格中了
至于list-name这个属性,需要结合screen来看。由于form的定义中只说明了有几个属性(几列),具体有多少行多少个record则是在screen中设定的。代码如下:

	<screen name="ListFormScreen">
	<section>
	  <actions>
	    <set field="row1.firstName" value="First1"/>
	    <set field="row1.lastName" value="Last1"/>
	    <set field="row2.firstName" value="First2"/>
	    <set field="row2.lastName" value="Last2"/>
	    <set field="row3.firstName" value="First3"/>
	    <set field="row3.lastName" value="Last3"/>
	    <set field="listOfRecords[]" from-field="row1"/>
	    <set field="listOfRecords[]" from-field="row2"/>
	    <set field="listOfRecords[]" from-field="row3"/>
	  </actions>
		<widgets>
	    <decorator-screen name="xhtml-decorator">
	      <decorator-section name="title">
	        <label text="A Screen with a list of forms."/>
	      </decorator-section>
	      <decorator-section name="body">
	        <include-form name="ListForm"   
	                     location="component://learning/widget/learning/LearningForms.xml"/>
	        <include-screen name="ShowProcessing"/>
	      </decorator-section>
	    </decorator-screen>
	  </widgets>
	</section>
	</screen>

很明显,我们在action中设定了有多少个record。我们注意到有这样的几句:

<set field="listOfRecords[]" from-field="row1"/>
<set field="listOfRecords[]" from-field="row2"/>
<set field="listOfRecords[]" from-field="row3"/>

如果我将form定义中的list-name改为listOfRecords1,重新访问

可以看到,所有内容都无法显示了
如果将row2的field改为listOfRecords1,则


所以,我认为,list-name定义了表中一个完整的行的类型名称,这个名称是在screen中使用的。只有将field设定为${list-name}+[]的形式,他才能特指表中的一行。

Multi类型

代码如下:

	<form name="MultiForm" type="multi" list-name="listOfRecords" 
      		target="processMultiForm" separate-columns="true">
		<field name="firstName"><text/></field>
		<field name="lastName"><text/></field>
		<field name="_rowSubmit" title="Select"><check/></field>
		<field name="submit"><submit/></field>
	</form>

效果如下:

可以发现,multi类型的form的定义和list是很像的,只有type不同而已。
用途上的区别如下:
It is often useful to edit a whole list of records in one go, and then click a single Submit button to update them all. The single and the list type form widgets cannot allow this; they can only allow the update of a single record at every click of a Submit button. 
简单来说,就是一次可以提交多份,而不像list需要一个一个地提交。

Form中field元素

输入框

效果:

定义:<text/>
<field name="firstName"><text/></field>

获取内容的方法:
String firstName = request.getParameter("firstName");

提交按钮

效果:

定义:<submit/>
<field name="submit"><submit/></field>

check box

效果

定义:<check/>
<field name="_rowSubmit" title="Select"><check/></field>

如果将name改动一下,改成其他的

就会发现表头的那个全选没有了

Form中的其他元素

<alt-target>
<row-actions>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值