最近在做项目的时候,碰到了一个JSF的问题,就是输入组件设置了readonly属性之后,提交的时候就得不到该组件的值了,仔细研究了一番,才找到原因和解决方法。
具体的现象是这样的,一个输入框需要设置为不能让用户更改,但可以通过javascript改变,改变后提交,则在服务器端得到改变后的值进行处理。这种需求应该也是非常常见的,可是在用JSF实现时,却碰到了问题。具体JSF代码如下:
<h:form id="theForm">
<h:inputText id="theValue" readonly="true" value="#{readonlyBean.theValue}"/>
<h:commandButton value="Submit" action="#{readonlyBean.submit}"/>
<af:outputText value="Click" onclick="editReadonly();"/>
</h:form>
第一个<h:inputText>就是我们要研究的对象,第二个<h:commandButton>是提交的按钮,第三个<af:outputText>是为了有一个地方可以点击,点击后调用javascript来改变第一个组件的值,至于af是来自于ADF,ADF是Oracle的JSF实现,提供了更多的功能,为什么不用<h:outputText>呢?因为很奇怪,标准的JSF组件<h:outputText>竟然不接受onclick事件。总之,调用的editReadonly()的javascript代码如下
function editReadonly() {
document.getElementById('theForm:theValue').value = "ABCD";
}
在服务器端,Managed Bean中的代码如下:
public class ReadonlyBean {
private String theValue = "XYZ";
public void setTheValue(String aValue) {
this.theValue = aValue;
}
public String getTheValue() {
return theValue;
}
public String submit() {
System.out.println( this.getTheValue() );
return null;
}
}
以上代码就是开始给theValue以初始值XYZ,然后在提交时打印出theValue的值。
运行时,首先点击"Click",看到页面上的只读输入组件的值变成了ABCD,然后提交,发现服务器端打印出来的值仍然是XYZ,没有得到该输入框的新值。
然而如果直接用HTML来完成这一功能时,页面上有一个readonly的输入框,提交到一个servlet,在servlet中从request中得到该输入框的值打印出来,那么在用javascript改变了该输入框的值后,打印出来的值是变化之后的值,说明标准的HTML的readonly的值是会提交的。
怎么会这样呢?JSF的输入组件设为readonly之后似乎不提交自己的值?为了解决这一问题,首先查看JSF最后生成的HTML页面的源代码,似乎没有任何问题,也是解析成一个标准的HTML的<input>,那说明在页面这个值是确实存在,也被提交给JSF框架,只是在后台处理时JSF忽略了该组件,这非常奇怪,为什么要采取这个和标准HTML不一致的行为?是不是当前使用的JSF的实现的问题?在换了好几个JSF的实现之后(Oracle的实现,MyFaces的实现,Sun的RI实现),结果都是一样,看来只有看看实现的源代码才能找到原因了。
下载了MyFaces 1.2的源代码,然后首先找到HtmlInputText的renderer:HtmlTextRenderer,因为提交时首先调用组件的renderer的docode方法来解析request的参数。然后发现该类是扩展了HtmlTextRendererBase,之后发现是调用了HtmlRendererUtils.decodeUIInput()来解析的,在该方法的一开始,就发现如下语句:
if(isDisabledOrReadOnly(component))
return;
这里充分说明了在JSF中readonly和disable一样,都是不会将参数提交给后台的。
原因找到了,那为什么JSF会采用这种方式。解释可能要回到JSF是一个组件的框架这一点上来。因为<h:inputText>是一个组件,那一个只读的组件是不是就应该不能改变其值呢?
最后则说一下怎么绕过这一限制,从而实现我们一开始想要的功能。实现的方法则只能是加一个隐藏的输入组件,在javascript改变只读输入框时,也同时改变该隐藏的输入组件的值,那么提交后就能得到这个隐藏输入组件的值。
分享到:
相关推荐
JSF创建自定义组件
JSF分页组件2,JSF分页组件2
JSF自定义组件学习的好教材
jsf用户输入验证,jsf验证器,附页面、java、css代码
JSF中文教程JSF中文教程JSF中文教程JSF中文教程
一步一步教你如何在jsf中自定义组件,简单易学,有程序完整代码。通过这个小demo你可以进一步开发复杂的组件。
jsf 中文文档jsf 中文文档jsf 中文文档jsf 中文文档
深入讨论JSF中Tree2组件使用方法。
NULL 博文链接:https://madihe-126-com.iteye.com/blog/266276
JSF UI 组件详解
jsf自定义组件的框架,未完成请勿下载.....
NULL 博文链接:https://beanil.iteye.com/blog/904114
精通JSF中文教程精通JSF中文教程精通JSF中文教程精通JSF中文教程精通JSF中文教程精通JSF中文教程
RichFaces组件简介,复合组件,日期控件,Ajax标签, 轻松实现。RichFaces组件简介,复合组件,日期控件,Ajax标签, 轻松实现。RichFaces组件简介,复合组件,日期控件,Ajax标签, 轻松实现。
创建JSF自定义组件
1. JSF生命周期与组件概述 1.1 JSF生命周期 1.2 概述自定义组件 2. 简单实例 2.1 编码、解码 2.2 组件标签 2.3 使用自定义组件 2.4 自定义Renderer
只要介绍JSF中各个组件标签的用法,对初学者来说是个很不错的资料哦!
JSF实战的附录文档,包括JSF的各种标签的使用,JSF组件的后台操作方法,很详细的介绍。
package composite component into jar maven3 jsf2 UBuntu glassfishv3.0.1 Emacs JDEE
利用JSF2.0和servlet3.0做的上传的例子,并实现单个文件上传的组件,虽然有些小限制,但是对单个上传功能完全可以实现。花了一整天的时间来研究啊,不容易!顶起吧。有什么想法请发表评论