posts - 0,  comments - 1,  trackbacks - 0
最近在做项目的时候,碰到了一个JSF的问题,就是输入组件设置了readonly属性之后,提交的时候就得不到该组件的值了,仔细研究了一番,才找到原因和解决方法。

具体的现象是这样的,一个输入框需要设置为不能让用户更改,但可以通过javascript改变,改变后提交,则在服务器端得到改变后的值进行处理。这种需求应该也是非常常见的,可是在用JSF实现时,却碰到了问题。具体JSF代码如下:
1       <h:form id="theForm">
2         <h:inputText id="theValue" readonly="true" value="#{readonlyBean.theValue}"/>
3         <h:commandButton value="Submit" action="#{readonlyBean.submit}"/>
4         <af:outputText value="Click" onclick="editReadonly();"/>
5       </h:form>
第一个<h:inputText>就是我们要研究的对象,第二个<h:commandButton>是提交的按钮,第三个<af:outputText>是为了有一个地方可以点击,点击后调用javascript来改变第一个组件的值,至于af是来自于ADF,ADF是Oracle的JSF实现,提供了更多的功能,为什么不用<h:outputText>呢?因为很奇怪,标准的JSF组件<h:outputText>竟然不接受onclick事件。总之,调用的editReadonly()的javascript代码如下:
1         function editReadonly() {
2             document.getElementById('theForm:theValue').value = "ABCD";
3         }
在服务器端,Managed Bean中的代码如下:
 1 public class ReadonlyBean {
 2     private String theValue = "XYZ";
 3     
 4     public void setTheValue(String aValue) {
 5         this.theValue = aValue;
 6     }
 7 
 8     public String getTheValue() {
 9         return theValue;
10     }
11 
12     public String submit() {
13         System.out.println( this.getTheValue() );
14         
15         return null;
16     }
17 }
以上代码就是开始给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()来解析的,在该方法的一开始,就发现如下语句:
1         if(isDisabledOrReadOnly(component))
2             return;
这里充分说明了在JSF中readonly和disable一样,都是不会将参数提交给后台的。

原因找到了,那为什么JSF会采用这种方式。解释可能要回到JSF是一个组件的框架这一点上来。因为<h:inputText>是一个组件,那一个只读的组件是不是就应该不能改变其值呢?

最后则说一下怎么绕过这一限制,从而实现我们一开始想要的功能。实现的方法则只能是加一个隐藏的输入组件,在javascript改变只读输入框时,也同时改变该隐藏的输入组件的值,那么提交后就能得到这个隐藏输入组件的值。
posted on 2009-02-24 10:22 飞马凉 阅读(1670) 评论(1)  编辑  收藏


FeedBack:
# re: JSF中输入组件的readonly属性[未登录]
2013-06-04 12:45 | doudou
好办法,只能这样了。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

留言簿

文章档案

搜索

  •  

最新评论