我有一个JSF页面,在这个页面中,我在<h:dataTable>中迭代一个列表,以显示一些包含复选框、一些文本和一个文本框的行。
我必须验证<h:dataTable>,以便当用户选中复选框时,他必须在文本框中输入一些文本。
这是我的JSF页面。
<h:form prependId="false" id="form">
<h:dataTable id="rm" width="100%" cellspacing="4"
value="#{controller.alertTriggers}" var="alt"
columnClasses="c1,c2,c3,c4">
<h:column>
<h:selectBooleanCheckbox value="#{alt.checkValue}" id="checkbox"/>
</h:column>
<h:column>
<h:outputText value="#{alt.id}" />
</h:column>
<h:column>
<h:outputFormat value="#{alt.msg1}" />
</h:column>
<h:column>
<h:message for="emailID" id="email" styleClass="validation-error"/>
<h:inputText value="#{alt.mailId}" id="emailID" style="width: 87%;" />
</h:column>
</h:dataTable>
</h:form> 我给出了所有复选框的id为checkbox,所有文本框的id为emailID。当呈现页面时,在检查页面源时,我发现复选框的ids是‘rm:0:复选框’,‘rm:1:复选框’.这些文本框是“rm:0:emailID”,“rm:1:emailID”。
在控制器中,我希望访问使用以下代码的这些动态文本框和复选框:
FacesContext context = FacesContext. getCurrentInstance();
for (int i=0;i<9;i++){
UIInput u=(UIInput) FacesContext.getCurrentInstance().getViewRoot().findComponent( "form:rm:" +i+":checkbox" );
if ((Boolean) u.getValue()){
UIInput ui=(UIInput) FacesContext.getCurrentInstance().getViewRoot().findComponent( "form:rm:" +i+":emailID" );
//code
}
}但这给了java.lang.NullPointerException
即使使用代码:
UIInput u=(UIInput) FacesContext.getCurrentInstance().getViewRoot().
findComponent( "form:rm:0:checkbox" ); gives the same exception.但如果我用
UIInput u=(UIInput) FacesContext.getCurrentInstance().getViewRoot().
findComponent( "form:rm:checkbox" );它没有给出一个空指针异常,但我不知道它是否给出了哪个复选框的值。
所以,总之,
JSF以rm:1:复选框、rm:2:复选框等形式生成it,但是当我试图访问JSF中的这个UI组件时,我无法这样做.
我漏掉了什么吗?
发布于 2013-09-02 12:51:31
FacesContext#getViewRoot()返回JSF组件树。在考虑了所有taghandlers (JSTL、<ui:include>等)之后,这就是XHTML源代码所表示的完全相同的树。您需要认识到,其中只有一个, <h:selectBooleanCheckbox id="checkbox">。它在UIViewRoot#findComponent()中是可用的,确切的ID是"form:rm:checkbox"。
它只是它的HTML表示,根据父<h:dataTable>的当前迭代周期多次重新生成。此生成的HTML表示形式反过来具有带有当前行索引内联的客户端in。这种HTML表示显然在组件树中不可用。
组件的状态(提交的值等)在迭代<h:dataTable>时也仅是可用的<h:dataTable>,而不是在<h:dataTable>之前或之后。本质上,您试图访问bean的action方法中的组件的值,而<h:dataTable>组件没有迭代它,所以这些值总是返回null。
为了以编程方式模拟<h:dataTable>迭代,以便收集所需的值,您需要通过UIComponent#visitTree()访问<h:dataTable>并收集VisitCallback实现中感兴趣的信息。
UIData table = (UIData) viewRoot.findComponent("form:rm");
table.visitTree(VisitContext.createVisitContext(FacesContext.getCurrentInstance()), new VisitCallback() {
@Override
public VisitResult visit(VisitContext context, UIComponent target) {
if (target instanceof HtmlSelectBooleanCheckbox) {
HtmlSelectBooleanCheckbox checkbox = (HtmlSelectBooleanCheckbox) target;
System.out.println("id: " + checkbox.getId());
System.out.println("value: " + checkbox.getValue());
// Collect them in an arraylist orso.
}
return VisitResult.ACCEPT;
}
});,但是,,在解决具体问题方面,您完全走错了方向。您应该在与要验证的输入组件相关联的验证器中执行验证,而不是在action方法中。下面是如何解决特定的具体功能需求:只有在选中同一行的复选框时,才能将输入字段验证为required:
<h:column>
<h:selectBooleanCheckbox binding="#{checkbox}" ... />
</h:column>
<h:column>
<h:inputText ... required="#{checkbox.value}" />
</h:column>就这样。另外的优点是,验证器在<h:dataTable>迭代时运行,所以您也不需要所有的visitTree()代码。
https://stackoverflow.com/questions/18573168
复制相似问题