国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
Creating a Theme in Struts 2 | Vita Rara: A L...
Categories: |

Struts 2 has a very powerful set of user interface tags (UI Tags). These tags are tightly integrated with the framework, taking full advantage of things like the OGNL Value Stack. The power this gives to a user it tremendous.

Struts 2 UI Tags

The Struts 2 UI Tags are backed with templates that do the actual rendering of HTML. You can change them without any need to touch the implementing classes. As of Struts 2.0.2 these templates are written in the FreeMarker template language. A quick look at the Freemarker Manual will provide you a quick overview of the language, and is helpful if you have questions about the language. Anyone familiar with JSP, PHP, or other template languages can quickly grasp it.

The Sample Application

Download the sample application, linked below. This is a Maven 2 project. To build the application run: "mvn package". This will create a war file in the target directory called: struts2themes.war. Deploy this war file to your Servlet container, such as Tomcat.

The XHTML Theme

Struts 2 ships with several themes, including a simple one that simply outputs the html form tags. The theme we are going to start with is the XHTML theme. This theme is designed to output valid XHTML markup, and by default lays forms out in a two column table with the label for each input field in the left column and the input field in the right column. This will get us started.

To see the layout created by this theme click the "Standard XHTML Form" button in the sample application.

This JSP markup to create this form is quite simple, and is a testament to the power of the Struts 2 UI Tags:

<s:form action="some.action" method="post" theme="%{currentTheme}"><s:textfield label="First Name" name="firstName"/><s:textfield label="Last Name" name="lastName"/><s:textfield label="Address 1" name="address1"/><s:textfield label="City" name="city"/><s:textfield label="State" name="state"/><s:textfield label="Zip" name="postalCode"/><s:submit value="Create Party" align="center"><s:param name="colspan" value="%{tableColSpan}" /><s:param name="align" value="%{‘center‘}" /></s:submit></s:form>

As you can see the template contains no HTML markup at all. All of the layout is done by the tags, and the templates that back them. Using these tags you can save an enormous amount of time writing table, tr and td tags.

The issue though is that many web applications contain forms that are far more complicated than are accommodated using a two column layout. Sometimes we need to do column spans, row spans, and use more then two columns.

Sometimes we need a form that looks like this:

This is an eight (8) column layout from a project I‘m currently working on called Quadran. An excerpt from the JSP source code:

<s:textfield label="Requested Delivery Date" name="order.dutyPrepaid"><s:param name="labelcolspan" value="%{2}" /><s:param name="inputcolspan" value="%{2}" /></s:textfield><s:textfield label="Third Party Bill To" name="order.dutyPrepaid"><s:param name="labelcolspan" value="%{2}" /><s:param name="inputcolspan" value="%{2}" /></s:textfield><s:textfield label="Trucker" name="order.dutyPrepaid" size="70"><s:param name="labelcolspan" value="%{2}" /><s:param name="inputcolspan" value="%{6}" /></s:textfield><s:textfield label="Loading Instructions" name="order.dutyPrepaid" size="70"><s:param name="labelcolspan" value="%{2}" /><s:param name="inputcolspan" value="%{6}" /></s:textfield><s:textfield label="Shipping Instructions" name="order.dutyPrepaid" size="70"><s:param name="labelcolspan" value="%{2}" /><s:param name="inputcolspan" value="%{6}" /></s:textfield>

S2 Tags Overview

The Struts tags are a powerful set of tags usable in JSP, FreeMarker and Velocity. They are completely integrated into the Struts 2 framework, taking advantage of the ValueStack and the OGNL expression language. Additionally the UI tags are backed by template. This allows the markup they generate to be changed without resorting to editing the Java source files. It‘s as easy as including your template files on your classpath.

Let‘s start with a simple example. We will examine the template that backs the <s:textfield> tag from the simple theme. (This file can be found in core/src/main/resources/template/simple in the Struts 2 source.)

<input type="text"<#rt/>name="${parameters.name?default("")?html}"<#rt/><#if parameters.get("size")?exists>size="${parameters.get("size")?html}"<#rt/></#if><#if parameters.maxlength?exists>maxlength="${parameters.maxlength?html}"<#rt/></#if><#if parameters.nameValue?exists>value="<@s.property value="parameters.nameValue"/>"<#rt/></#if><#if parameters.disabled?default(false)>disabled="disabled"<#rt/></#if><#if parameters.readonly?default(false)>readonly="readonly"<#rt/></#if><#if parameters.tabindex?exists>tabindex="${parameters.tabindex?html}"<#rt/></#if><#if parameters.id?exists>id="${parameters.id?html}"<#rt/></#if><#if parameters.cssClass?exists>class="${parameters.cssClass?html}"<#rt/></#if><#if parameters.cssStyle?exists>style="${parameters.cssStyle?html}"<#rt/></#if><#if parameters.title?exists>title="${parameters.title?html}"<#rt/></#if><#include "/${parameters.templateDir}/simple/scripting-events.ftl" /><#include "/${parameters.templateDir}/simple/common-attributes.ftl" />/>

This template is written in FreeMarker. It starts by emitting the beginning of an input tag of type text on the first line. Then using #if statements it examines the various possible parameters to the tag and outputs the appropriate HTML. Near the bottom it includes two additional scripts: scripting-events.ftl and common-attributes.ftl for handling scripting and attributes that are common to all HTML tags.

This method of building scripts by including others is used pervasively throughout the templates.

The parameters that are passed into the tag via attributes are available using the parameters object. We will use this object to access additional parameters to extend the XHTML theme.

Our New Theme

The goal of our new theme is to extend the XHTML theme to support layout of forms using an arbitrary number of columns. The default XHTML theme only support a two column layout, with labels on the left and inputs on the right, each in their own <td>.

Our theme will have the following attributes:

  • Allow for an arbitrary number of columns in the table containing our form,
  • Require no use of HTML markup,
  • Allow for arbitrary display of data integrated into our theme that isn‘t an HTML input,
  • Allow the number of columns to be specified for the label, and the input independently,
  • Inputs will not require a label, and if none is present no table elements will be emitted for the label.

The qTableLayout Bean

To specify the configuration of our table layout for our form we need to create a bean prior to the opening <s:form> tag. I have experimented to no avail using the <s:param> tag to parameterize the <s:form>, but have not succeeded. To work around this we simple create a bean holding our table configuration before we start our form.

<s:bean name="java.util.HashMap" id="qTableLayout"><s:param name="tablecolspan" value="%{4}" /></s:bean>

The qTableLayout is a HashMap and holds one property, tablecolspan, which is the number of columns we want our form to use. The sample above would produce a layout using four columns.

Accessing the qTableLayout Bean in FreeMarker

One of the keys to making our theme work is being able to access the qTableLayout bean in our FreeMarker templates, change values contained in it, using it as a means of passing information between our tags. We use it to maintain the state of our table. Particularly the number of columns we have emitted for the current row.

To update the qTableLayout bean we use the following in the FreeMarker template:

${stack.setValue(‘#qTableLayout.currentColumnCount‘, columnCount)}

This statement accesses the OGNL ValueStack and stores the currentColumnCount in our qTableLayout bean. This allows our theme to maintain state between each invocation of the FreeMarker templates that back the Struts 2 tags.

Table Layout Logic

When creating a new theme it‘s usually better to start with an existing theme and extend it. For our example we will start with the XHTML theme. To start the new theme you would make a template directory in your WEB-INF/classes directory, then in that one make a directory with the same name as your theme, in our case "qxhtml". Then copy all of the files from the XHTML theme in the Struts 2 distribution into qxhtml to form the basis of our new theme. (NB: You don‘t need to do all of this. It‘s already done in the sample app.)

With all of our templates in our directory it‘s time to start hacking. We need to control the emitting of the <tr> tags. These are emitted by default in the XHMTL theme. The first thing we need to do is remove these from the XHTML template. These statements are in the controlheader-core.ftl and controlfooter.ftl templates in the XHTML theme. In qxhtml these have been removed and two new files have been introduced: controlheader-trlogic.ftl and controlfooter-trlogic.ftl.

<#--controlheader-trlogic.ftlThis template handles:* intializing qTable.currentColumnCount if it has not been initialzed,* emiting a <tr> tag if the currentColumnCount == 0,--><#if qTableLayout.exists && ! qTableLayout.currentColumnCount?exists ><#-- Set the currentColumnCount to 0 because this is the first row of the table. -->${stack.setValue(‘#qTableLayout.currentColumnCount‘, 0)}</#if><#-- Do we need to write the opening tr tag. --><#if qTableLayout?exists && qTableLayout.tablecolspan?exists ><#assign columnCount = qTableLayout.currentColumnCount /><#else><#-- Set the currentColumnCount to 0 because this is the first row of the table. -->${stack.setValue(‘#qTableLayout.currentColumnCount‘, 0)}<#assign columnCount = 0 /></#if><#if columnCount == 0><#-- Write out the opening tr tag to start the table row. --><tr><#rt/></#if>

As you can see in this listing the qTableLayout bean is used to hold the currentColumnCount, which is used to if we need to emit a <tr> tag when the column count equals zero (0). In the controlfooter-trlogic.ftl template if the current column count is equal to or greater than the qTableLayout.tablecolspan the template will emit our closing <tr> tag.

Using Our New Theme

The qxhtml theme supports more than just doing a multi-column layout. It also supports specifying the number of columns you would like the label and the input to be using <s:param> tags. Here‘s a quick snippet from our complex example above:

<s:textfield label="Loading Instructions" name="order.dutyPrepaid" size="70"><s:param name="labelcolspan" value="%{2}" /><s:param name="inputcolspan" value="%{6}" /></s:textfield>

Inside our <s:textfield> tag we have nested two <s:param> tags, one to specify the number of columns for our label, and the input. This allows us great flexibility in laying out our forms.

Out theme also supports simply out putting an input without a label. Just omit the label from your tag:

<s:textfield name="someProperty" />>

This will emit a <td> containing an HTML input only. No label will be generated. This allows you to do tabular inputs very simply as follows:

<s:textfield name="propertyOne" />><s:textfield name="propertyTwo" />><s:textfield name="propertyThree" />><s:textfield name="propertyFour" />>

If you configured your form to have four (4) columns this would result in one row. Wrap this in an <s:iterator> tag and you can quickly create tabular input screens for updating large numbers of records.

The Sample App

The sample application contains one form in form.jsp. Deploy the application and view it. If you‘ve deployed this on your local machine using Tomcat you can go to: http://localhost:8080/struts2themes/. Click the "Standard XHTML Form," "Four Column," and "Six Column" buttons to view the form in two, four and six column layout. Each of these layouts is produced from the exact same markup. The only difference is the a property of the action that sets the number of columns to use.

To see a complex form click "Complex Form" in the navigation. This is a subset of the complex form in the screen shot above. The source for the form is:

<%-- Setup the number of columns to be in the table layout for the form. --%><s:bean name="java.util.HashMap" id="qTableLayout"><s:param name="tablecolspan" value="%{8}" /></s:bean><s:form action="complexForm.action" method="post" theme="qxhtml"><s:textfield label="SO Number" name="order.fromPartyOrderNumber"><s:param name="labelcolspan" value="%{2}" /><s:param name="inputcolspan" value="%{2}" /></s:textfield><s:select name="salespersonId" label="Salesperson" list="genericList" listKey="id" listValue="name"><s:param name="labelcolspan" value="%{2}" /><s:param name="inputcolspan" value="%{2}" /></s:select><s:textfield label="Trucker" name="order.dutyPrepaid" size="70"><s:param name="labelcolspan" value="%{2}" /><s:param name="inputcolspan" value="%{6}" /></s:textfield><s:select name="newPoRequired" label="New PO Required" list="genericList"listKey="id" listValue="name" /><s:select name="shipdateConfirmed" label="Ship Date Confirmed"list="genericList" listKey="id" listValue="name" /><s:select name="accounting90EntryDone" label="Acctg Entry Done"list="genericList" listKey="id" listValue="name" /><s:select name="factored" label="Factored" list="genericList" listKey="id"listValue="name" /><tr><th align="center" colspan="8">Line Items</th></tr><tr><th>#</th><th>Product</th><th>Qty</th><th>Unit Price</th><th>Allocation Instructions</th><th>Label Instructions</th><th>Description</th><th>Override Reason</th></tr><s:iterator value="lineItems" status="status"><s:component template="/components/textcell.ftl" value="%{#status.index}" /><s:select name="termsId" list="genericList" listKey="id" listValue="name" /><s:textfield name="test" size="1"/><s:textfield name="test" size="1"/><s:textfield name="test" size="1"/><s:textfield name="test" size="1"/><s:textfield name="test" size="1"/><s:textfield name="test" size="1"/></s:iterator><s:submit value="Create Sales Order" align="center"><s:param name="colspan" value="%{8}" /><s:param name="align" value="%{‘center‘}" /></s:submit></s:form>

This sample shows the full power of the theme at this point. It uses variable label and input column spans, textfield without labels, and a custom component for outputting text in a table data, but including it in the theme and counting columns so the table rows are started appropriately. (Look at the first tag inside the iterator for the component.)

Here‘s what it looks like:

Future Improvements

This theme is very usable in its current form. There are some things I‘d like to add. The most important of these is row spanning. I have some ideas on how to do it, but haven‘t tackled it. Other improvements could be had with a minor change to the existing Struts 2 tags, but that involved actually digging into the class files, and I‘m not ready for that yet. To be honest I‘ve never written a JSP tag. I have asked for some pointers on the Struts users list though. So, we‘ll see.

Attachment Size
struts2themes.tar_.gz 18.53 KB

Error if I do not define the qTableLayout bean

If I have a form where I do not set the qTableLayout bean, I get this error:

Method public void com.opensymphony.xwork2.util.OgnlValueStack.setValue(java.lang.String,java.lang.Object) threw an exception when invoked on com.opensymphony.xwork2.util.OgnlValueStack@1352367
The problematic instruction:
----------
==> ${stack.setValue(‘#qTableLayout.currentColumnCount‘, 0)} [on line 15, column 9 in template/qxhtml/controlheader-trlogic.ftl]
in include "/${parameters.templateDir}/qxhtml/controlheader-trlogic.ftl" [on line 1, column 1 in template/qxhtml/submit.ftl]
----------

Java backtrace for programmers:
----------

[ Bunch of stuff removed ]

Caused by: ognl.OgnlException: target is null for setProperty(null, "currentColumnCount", 0)

This happened because I change the default theme in struts and did not update all the forms in the webapp.

Is there a way to tell qxhtml to work like xhtml if qTableLayout is not defined?

Fix for qTableLayout errro

Mark:

I changed controlheader-trlogic.ftl to have this code and it worked:

tag if the currentColumnCount == 0,
-->

${stack.setValue(‘#qTableLayout.currentColumnCount‘, 0)}

${stack.setValue(‘#qTableLayout.currentColumnCount‘, 0)}

You probably want to update your code with this as well.

Thanks,
Neil

Formatting messed up

Mark:

It looks like your blog did not like the freemarker template code. It probably interpreted it as HTML.

I posted it here:
http://jamm5.jammconsulting.com/controlheader-trlogic.txt

Thanks,
Neil

Different style between label and input text field

Hi Mark,
Thanks for the nice how to.

Anyway, I have a question :)
What if we want to have different style (bgcolor for example), between input text element and its label?

Re: Different style between label and input text field

There is a cssClass argument to the Struts 2 UI components. Looking at the templates this applies to the actual input control. So, short of using an s:param tag there is no easy means of getting a different css class on the TD for the input or label TD‘s.

With that said, if you want to style all of your forms the same, the label TD does have a class of tdLabel. So you could easily use a style sheet to style that. Also the opening TD tag for the input element in is the controlheader.ftl template. You could add ‘class="tdInput"‘ to that, allowing you to also style it using your css style sheet.

Mark

Re: Different style between label and input text field

Thx Mark...it‘s not really clean though :(

Actually, first I prefer using simple "plain" theme which is the most flexible. But in simple theme, I lose the client side (pure javascript & ajax) validation. I could write javascript validation manually, but I hate to lose the integrated server and client side validation.

So I think I‘m gonna try to write a template that does the ‘a(chǎn)lert-style‘ javascript validation, like in the old Struts 1.x.

How do make 2 buttons align within one row?

I find your article very useful in designing forms. However, I have one problem here, how do I align 2 buttons using the <s:submit> tag right in a single row? By default, the <s:submit> tag will create a row for each button. I want the 2 buttons to appear on the same row.

Thanks!

How to do|

You must use CSS =)
====part of css===
input.button{
float:left;
}
======end of css ======
use this css class for both buttons and you‘ll get what you want=)

Aligning Submit Buttons

Using this theme you can have as many submit buttons as will fit on a row. If you look at the sample you‘ll see that it takes an argument for the number of columns and its alignment.

Mark

Sample App

Hello, Mark.
First, thanks for the awesome howto‘s. I‘m curently doing some webworking but hadn‘t enough time to get into all that complex stuff like themes and components; so your tutorial is big help for me, you should try to add links to them to the struts 2 project site imho.

Anyway, what about the sample app link you mentioned ? I didnt managed to find any on this page. Can you post it here ?

Regards, Sergey Pariev.

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
struts2中form的theme屬性
Struts2 標(biāo)簽庫(kù) [Tablib] (轉(zhuǎn)) - 蘭色的海洋 - 51CTO技術(shù)博客
struts2中的日期格式化輸出
Struts2中OGNL,valueStack,stackContext的學(xué)習(xí)
Struts2+json中的異常
strus2標(biāo)簽大總結(jié)(全)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服