随笔-348  评论-598  文章-0  trackbacks-0
在新项目中,我们要做一个这样的功能:有一个表格,没有记录,当用户点击“添加”的时候,会生成一条行,里面包含了文本输入框,下拉框等等,需要用户填写,以此类推,用户只要需要,他可以填写无限条信息,最后点击一个“保存”来保存所有记录。
 这里,我们为了提高用户的体验性,使用了Ajax技术,后台生成一个HtmlInputText控件实例添加到指定的panel中,然后刷新表格那一部分显示出来。

一上来,我用了这个方法(添加到监听器中):
HtmlInputText text = new HtmlInputText();
panel.getChildren().add(text);
然后当填写了值之后调用了text.getValue()方法,发现打印出来的是null,以为JSF无法捕获Ajax生成控件的值,又尝试设定了Action来生成控件,发现还是不行。

最后只好使用了这个办法:
HtmlInputText text = new HtmlInputText();
text.setId(
"text_1");
panel.getChildren().add(text);
获取方法使用了:
public void sendMessage(ActionEvent e)
{
FacesContext context 
= FacesContext.getCurrentInstance();
UIViewRoot view 
= context.getViewRoot();
HtmlInputText output 
=
(HtmlInputText)view.findComponent(
"messageForm:text_1");
System.out.println(output.getValue());
}
不管是用Ajax方式还是表单提交的方式都可以使用这个方法获得。所以我就在想,这个是什么原因,直接设置实例反而没有办法操作,还要重新获取才可以。
但是如果你在初始化控件的时候进行text.setValue("111");操作还是可以的,这样输入框就会默认出现值111。

大家有什么看法,尽管发表,如果对这个需求有更好的解决方案,也请提出来,谢谢了。

---------------------------------------------------------
专注移动开发

Android, Windows Mobile, iPhone, J2ME, BlackBerry, Symbian
posted on 2008-11-27 17:18 TiGERTiAN 阅读(2093) 评论(9)  编辑  收藏 所属分类: JavaJSF

评论:
# re: 探讨JSF Backing bean生成控件的问题 2008-11-27 19:22 | Libo
是否使用binding?如果不使用应该是不能得到值的.  回复  更多评论
  
# re: 探讨JSF Backing bean生成控件的问题 2008-11-27 23:51 | TiGERTiAN
@Libo
页面上面的panel控件使用了binding,绑定到了后台的一个实例,在后台我也是对这个实例进行添加子控件的操作,也就是说子控件原来在前台页面是什么痕迹都没有的,完全即时生成,然后我想操作后台子控件的实例获取用户输入的值就不可以。。  回复  更多评论
  
# re: 探讨JSF Backing bean生成控件的问题 2008-11-28 07:40 | Libo
这样应该是在后台得到panel组件,然后类似于这样的代码:
List l =panel.getValue();
或是
panel.getChildren(); 这要根据panel绑定的是什么组件.
之后对list 遍历,得出的是每个组件,然后对组件取值.  回复  更多评论
  
# re: 探讨JSF Backing bean生成控件的问题 2008-11-28 10:45 | TiGERTiAN
@Libo
我也尝试过了你说的两种方法,每个控件的实例都得到了,但是调用每个控件的getValue(),都得不到用户输入的值。  回复  更多评论
  
# re: 探讨JSF Backing bean生成控件的问题 2008-11-28 14:38 | huliqing
不过我倒是觉得这个功能可以不需要用到ajax.
使用js在客户端直接生成子组件,不过这不会直接反映到JSF的组件树中.可能需要作一些特殊处理,比如扩展一下inputText组件.
使用action进行生成子组件应该会刷新页面,不过这应该是JSF正常的方式,但是你的例子看起来很正常.
不过我估计可能的问题应该是出现了这样的流程:
点击action - 后台生成子组件(无默认值) - 重新渲染页面(这时页面viewState中panel的子组件仍没有值) - 使用ajax调用(把无值的viewState带到了后台) - 出现以上错误!
呵呵,以上是我对你的错误原因的流程猜测.
不知道你的整个操作过程是怎么样的.  回复  更多评论
  
# re: 探讨JSF Backing bean生成控件的问题[未登录] 2008-11-29 00:08 | David
很久以前分析过JSF源代码:)

JSF每一次Request-Response包含六个阶段,其中在response render之前JSF server端有一个component tree,而render就是把这个component tree 生成对应的html,这个生成的html(包含form)被提交的时候(另一个request-response),server段重新恢复一个view。而你的这个sendMessage(apply application values吧,不记得了)发生在restore之后,所以能够取到值。

因为ajax的context根jsf的context属于不同进程,所以不能ajax的html 不能直接渗透到JSF中访问component tree。

我的想法就是
设置一个agent驻留在jsf application中,即每个agent实例与每一个jsf request-response在同一分配的thread中,agent可以访问jsf数据。而这个agent有一个http方法,以ajax提供的jsf sessionid为主要参数,用来更新jsf component tree,然后局部递归render,把rendered的html代码加在html中
。这样,不管server,还是client都有同结构的tree.

  回复  更多评论
  
# re: 探讨JSF Backing bean生成控件的问题 2008-11-29 00:35 | TiGERTiAN
@David
大概看懂了你的意思,只是不太明确代码如何编写,请问您有示例代码提供给我参考下吗?谢谢您了。  回复  更多评论
  
# re: 探讨JSF Backing bean生成控件的问题 2008-11-29 00:42 | TiGERTiAN
@David
还有就是,我的流程是后端生成HtmlInputText实例,把这个实例添加到panel中:
HtmlInputText text = new HtmlInputText();
panel.getChildren().add(text);
然后前端调用Ajax直接渲染出来新的控件,如果后端在声明实例之后又设置了setValue("1111"),前端是可以看到刚才设置的1111的。
问题就在于,如果我想获得用户输入的数据,直接调用刚才生成的实例text的getValue()方法是无法获得用户输入的值的,只能获得我刚才设置的1111,我在想可能JSF前端页面绑定的实例已经不是我后端设置的这个了,是他自己生成的一个HtmlInputText,所以才只能用findComponent方法通过ID找到该控件。  回复  更多评论
  
# re: 探讨JSF Backing bean生成控件的问题 2008-11-29 01:01 | TiGERTiAN
@huliqing
应该不是这个原因  回复  更多评论
  

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


网站导航: