使用Ajax的3个级联下拉菜单

时间:2011-11-24 23:36:40

标签: ajax jsf-2 primefaces

我想修改PrimeFaces展示应用中的示例"ajaxify select",并根据第二个p:selectOneMenu的选择引入第三个p:selectOneMenu

以下是修改后的代码:

<h:form>  
    <p:growl id="msgs" showDetail="true"/>  
    <p:panel header="Double Combo" style="margin-bottom:10px;">  
        <h:panelGrid columns="3" cellpadding="5">  
            <p:selectOneMenu id="city" value="#{pprBean.city}">  
                <f:selectItem itemLabel="Select City" itemValue="" />  
                <f:selectItems value="#{pprBean.cities}" />  
                <p:ajax update="suburbs"  
                        listener="#{pprBean.handleCityChange}" />  
            </p:selectOneMenu>  

            <p:selectOneMenu id="suburbs" value="#{pprBean.suburb}">  
                <f:selectItem itemLabel="Select Suburb" itemValue="" />  
                <f:selectItems value="#{pprBean.suburbs}" />  
                <p:ajax update="subsuburbs"  
                    listener="#{pprBean.handleSuburbChange}" />  
            </p:selectOneMenu>  

            <p:selectOneMenu id="subsuburbs" value="#{pprBean.subsuburb}">  
                <f:selectItem itemLabel="Select Subsuburb" itemValue="" />  
                <f:selectItems value="#{pprBean.subsuburbs}" />  
            </p:selectOneMenu>  
        </h:panelGrid>  

        <p:separator />  

        <p:commandButton value="Submit" update="msgs" 
            actionListener="#{pprBean.displayLocation}"/>  
    </p:panel>  
</h:form> 

但是从不执行侦听器函数#{pprBean.handleSuburbChange}。我在另一个论坛中看到,ajax响应中的动态代码不包含更新属性中指示的其他标记,但我该怎么办呢?

PPRBean代码中,我添加了:

@Named("pprBean")
@RequestScoped
public class PPRBean implements Serializable {

    // ...

    public void handleSuburbChange() {
        if (suburb != null && !suburb.equals("")) {
            subsuburbs = subsuburbsData.get(suburb);
        } else {
            subsuburbs = new HashMap<String, String>();
        }
        log.info("subsuburbs:" + subsuburbs);
    }

    // ...

1 个答案:

答案 0 :(得分:0)

如果无法处理所选项目,则不会调用侦听器。您已将bean放在请求范围中,这意味着当与请求关联的响应完成时(即,当浏览器完成加载页面时),它就会被填充。因此,当您提交表单时,将触发一个新请求并创建一个全新的bean,在您的情况下,显然不会准备/预填充(post)构造函数中的郊区列表以查找所选项目(并执行监听器。)

要解决此问题,您通常需要通过JSF @ViewScoped注释和@ManagedBean将bean放在视图范围内。

@ManagedBean
@ViewScoped
public class Bean {
    // ...
}

这样,只要您与同一视图交互,bean实例就会存在。但是当您使用CDI来管理bean而不是JSF时,您需要使用@ConversationScoped代替并自己控制Conversation

@Named
@ConversationScoped
public class Bean {

    @Inject
    private Conversation conversation;

    @PostConstruct
    public void init() {
        conversation.begin();
        // ...
    }

    public void submit() {
        // ...
        conversation.end();
    }

}