如何从外部在p:accordionPanel的单个选项卡中更新AJAX组件?

时间:2015-07-16 16:44:17

标签: ajax jsf primefaces

我有p:accordionPanel代表项目列表,每个标签中都有一个表单。提交任何重复表单后,可能需要额外的数据,即弹出p:dialog时提示用户输入更多数据。该对话框是在手风琴面板之外定义的,因为与手风琴的项目不同,它们中只有一个可以一次显示,所以不需要在手风琴的每个标签中重复播放所提供的HTML。

手风琴的定义如下(简化但包含所有相关描述符):

<p:accordionPanel id="myAccordion" value="#{managedBean.getAccordionList}" var="item" multiple="false" dynamic="true" cache="true">

    <p:ajax event="tabChange" listener="#{managedBean.processTabChange}"/>

    <p:tab title="#{item.tabTitle}" id="itemTab">

        <h:form id="itemForm">

            <h:outputLabel for="itemName" value="Item Name:"/>
            <p:inputText id="itemName" title="Item Name:" 
                    maxlength="16" value="#{appeal.itemName}">
            </p:inputText>

因此,为itemName呈现的HTML在第一个实例中为myAccordion:0:itemForm:itemName,在第二个实例中为myAccordion:1:itemForm:itemName,等等。

对话框定义如下:

<p:dialog id="commentDialogID" header="Enter comment" widgetVar="commentDialog" modal="true" resizable="true" height="auto">
    <h:form id="commentForm">

        <h:outputLabel for="comment" value="Comment:"/>

        <p:inputTextarea id="comment" title="Comment" 
                rows="6" cols="33"
                value="#{managedBean.activeItem.comment}"
                required="true">
            <f:ajax render="comment"/>
        </p:inputTextarea>

        <h:commandButton value="Submit" action="#{managedBean.proceed}" onclick="PF('commentDialog').hide();">
            <f:ajax render="*** ??? ***"/>
        </h:commandButton>

    </h:form>
</p:dialog> 

我一再失败的是尝试f:ajax仅更新手风琴面板中的一个标签,即弹出对话框的活动标签。我尝试使用

:myAccordion:#{managedBean.activeItem.displayIndex}:itemForm:itemName
:myAccordion:#{managedBean.activeItem.displayIndex}:itemForm
:myAccordion:#{managedBean.activeItem.displayIndex}:itemTab

代替*** ??? ***,但没有一个会编译:

javax.faces.FacesException: <f:ajax> contains an unknown id ':myAccordion:0:itemForm' - cannot locate it in the context of the component j_idt20

如果我跳过索引标记(例如:myAccordion:itemForm:itemName),它会编译,但它在功能上没有任何作用。 Item实体类有一个getDisplayIndex,它可以准确地返回活动标签的索引。

我的问题与this question中描述的问题非常相似,它并没有真正有一个好的答案。可能是PrimeFaces的限制吗?

2 个答案:

答案 0 :(得分:1)

我不知道您正在使用的Primefaces版本,但这似乎是Primefaces 5.1.1中的一个错误,我可以重新创建此问题。通过升级到Primefaces 5.2,ajax EL可以突然找到引用的id。如果需要,我可以发布MCVE。

编辑:MCVE:

<强> XHTML:

<h:form id="itemForm">
    <p:accordionPanel id="myAccordion" binding="#{accordionView}" value="#{playgroundController.users}" dynamic="true" activeIndex="#{playgroundView.activeIndex}" var="user" multiple="false">

        <p:ajax event="tabChange" update="commentDialogID"/>

        <p:tab title="#{user.name}">
                <h:outputLabel for="itemName" value="Item Name:" />
                <p:inputText id="itemName" title="Item Name:" maxlength="16"
                    value="#{user.amount}">
                </p:inputText>
                <p:commandButton value="showDialog" onclick="PF('commentDialog').show();"></p:commandButton>
        </p:tab>

    </p:accordionPanel>
</h:form>

<p:dialog id="commentDialogID" header="Enter comment" widgetVar="commentDialog" modal="true" resizable="true" height="auto">
    <h:form id="commentForm">

        <h:outputLabel for="comment" value="Comment:"/>

        <p:inputTextarea id="comment" title="Comment" 
                rows="6" cols="33"
                value="#{playgroundView.activeIndex}"
                required="true">
            <f:ajax render="comment"/>
        </p:inputTextarea>

        <p:commandButton value="Submit" onclick="PF('commentDialog').hide();" update=":itemForm:myAccordion:#{playgroundView.activeIndex}:itemName" ></p:commandButton>

    </h:form>
</p:dialog> 

PlaygroundView Bean:

请注意,在此示例中,activeIndex必须具有初始值,否则此EL:

update=":itemForm:myAccordion:#{playgroundView.activeIndex}:itemName"

将错误地解决并将抛出一个错误,它无法找到引用组件的id。这当然有一个缺点,即第一个标签会在页面加载时打开,但这是另一个问题

private String activeIndex = "0";

public String getActiveIndex() {
    return activeIndex;
}

public void setActiveIndex(String activeIndex) {
    this.activeIndex = activeIndex;
}

PlaygroundController Bean:

private List<User> users;
@Override
    public void initializeView() {
    createUsers();
}

public void createUsers() {
        User user1 = new User();
        User user2 = new User();
        User user3 = new User();
        user1.setName("User123");
        user1.setAmount(1);
        user2.setName("User456");
        user2.setAmount(2);
        user3.setName("User12312345111111111111111111111111111");
        user3.setAmount(3);
        List<User> userList = new ArrayList<User>();
        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        users = userList;
    }

用户:

public class User implements Serializable {
    String name;
    int amount = 0;
}

答案 1 :(得分:0)

您应该在tabChange事件上更新commandButton。

<p:ajax event="tabChange" listener="#{managedBean.processTabChange}" update=":commentForm:commandButtonId"/>

render内的<f:ajax>属性<h:commandButton>在呈现阶段进行评估,而不是更快。因此,如果您不更新它,它将始终指向“0”。检查浏览器开发人员工具中的源代码并检查ajax请求(总是为调试做的事情)。您将看到带有':0:'的完整clientId,并且您不会在ajax请求中看到它发生变化。