根据h:selectOneRadio选择有条件地渲染h:selectOneMenu和h:inputText by ajax

时间:2013-04-11 14:13:52

标签: ajax jsf-2

我有一个带有2个单选按钮的表单:“type1”和“type2”。如果选择“type1”,则必须显示下拉列表。如果选择“type2”,则必须显示文本字段。

这是视图和控制器:

test.xtml

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:h="http://java.sun.com/jsf/html"
            xmlns:rich="http://richfaces.org/rich"
            xmlns:a4j="http://richfaces.org/a4j">


    <h:form>

        <h:selectOneRadio 
            id="type"
            label="Type"
            value="#{testBean.type}">
            <f:selectItem itemLabel="Type1" itemValue="type1" />
            <f:selectItem itemLabel="Type2" itemValue="type2" />
            <f:ajax execute="@all" render="selectBox inputBox"/>
        </h:selectOneRadio>

        <h:selectOneMenu
            id="selectBox"
            label="Service"
            value="#{testBean.service}"
            rendered="#{testBean.isType1}"
            style="width:285px">
            <f:selectItem itemLabel="Medium"  itemValue="medium" />
            <f:selectItem itemLabel="Basic"   itemValue="basic" />
            <f:selectItem itemLabel="Premium" itemValue="premium" />
        </h:selectOneMenu>
        <h:inputText 
            id="inputBox"
            size="50"
            value="#{testBean.custom}"
            rendered="#{!testBean.isType1}" />

    </h:form>

</ui:composition>

TestBean.java

package com.test.backing;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name = "testBean")
@SessionScoped
public class TestBean implements Serializable
{
private static final long serialVersionUID = -4337084623546767911L;

private String type = "type1";
private String service;
private String custom;

public Boolean getIsType1()
{
    if(type.equals("type1"))
    {
        System.out.println(type+":true");
        return true;
    }
    else
    {
        System.out.println(type+":false");
        return false;
    }
}

public String getType()
{
    return type;
}
public void setType(String type)
{
    this.type = type;
}

public String getService()
{
    return service;
}

public void setService(String service)
{
    this.service = service;
}

public String getCustom()
{
    return custom;
}

public void setCustom(String custom)
{
    this.custom = custom;
}

}

当我开始申请时,我的标准输出中有以下内容:

type1:true
type1:true
type1:true
type1:true
type1:true
type1:true

但是,当我选择其他类型时,UI中没有任何反应。这是怎么造成的,我该如何解决?

2 个答案:

答案 0 :(得分:4)

JSF生成HTML。 JS / Ajax适用于HTML。 JS / Ajax通过document.getElementById()在HTML DOM树中查找HTML元素并基于Ajax响应替换其内容来更新HTML元素。但是,如果指示JSF组件不呈现HTML,则JS / Ajax无法在HTML DOM树中找到它,因此无法替换任何内容。

您只能ajax更新始终呈现的JSF组件的HTML表示形式。所以,将它们包裹在例如<h:panelGroup>

<h:selectOneRadio ...> 
    <f:ajax ... render="selectAndInputBox" />
</h:selectOneRadio>
<h:panelGroup id="selectAndInputBox">
    <h:selectOneMenu ... rendered="..." />
    <h:inputText ... rendered="..." />
</h:panelGroup>

另见:


无关具体问题,getIsType1()方法笨拙。只需在视图中直接进行比较,这样就可以摆脱它。

<h:selectOneMenu ... rendered="#{testBean.type == 'type1'}" />
<h:inputText ... rendered="#{testBean.type != 'type1'}" />

或者更符合您的初始问题,

<h:selectOneMenu ... rendered="#{testBean.type == 'type1'}" />
<h:inputText ... rendered="#{testBean.type == 'type2'}" />

答案 1 :(得分:4)

尝试使用以下代码替换xhtml代码

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:h="http://java.sun.com/jsf/html"
            xmlns:rich="http://richfaces.org/rich"
            xmlns:a4j="http://richfaces.org/a4j">

<h:head>

</h:head>

<h:form prependId="false">

    <h:selectOneRadio 
        id="type"
        label="Type"
        value="#{testBean.type}">
        <f:selectItem itemLabel="Type1" itemValue="type1" />
        <f:selectItem itemLabel="Type2" itemValue="type2" />
        <f:ajax execute="@all" render="selectInputPanel"/>
    </h:selectOneRadio>
    <h:panelGroup id="selectInputPanel">
    <h:selectOneMenu
        id="selectBox"
        label="Service"
        value="#{testBean.service}"
        rendered="#{testBean.isType1}"
        style="width:285px">
        <f:selectItem itemLabel="Medium"  itemValue="medium" />
        <f:selectItem itemLabel="Basic"   itemValue="basic" />
        <f:selectItem itemLabel="Premium" itemValue="premium" />
    </h:selectOneMenu>
    <h:inputText 
        id="inputBox"
        size="50"
        value="#{testBean.custom}"
        rendered="#{!testBean.isType1}" />
    </h:panelGroup>
</h:form></ui:composition>

代码中的主要问题是,

  1. 缺少h:头部导入jsf ajax所需的jsf.js。
  2. 请按照@BaluC的建议将您的组件包装到panelGroup中,因为一旦组件未呈现(页面上不可用),则其上的ajax将无法使用其ID。
  3. 关于getIsType1()方法调用的时间数是由于渲染属性,有关更多信息,请查看@ Baluc的答案here