使用 PrimeFaces DF 打开多个对话框

Opening multiple dialogs with PrimeFaces DF

使用 PrimeFaces,我想打开多个不同的对话框。乍一看,一个简单的方法似乎是 PrimeFaces Dialog Framework。哪个在一定程度上起作用。

我有一个DataTable有记录,每条记录都可以开成一条新的Dialog。对于每条记录,打开此对话框都可以正常工作。但似乎 Dialog 似乎绑定到其调用父级的 ID。

下面是一个演示此问题的最小示例。考虑以下 xhtml.

<h:form id="indexForm">
    <p:dataTable id="indexTable" value="#{dFDemo.indexes}" var="index">
        <p:column sortBy="#{index}" headerText="index">
            <p:commandButton id="openDialogBtn" value="Open dialog #{index}"
                             action="#{dFDemo.openDialog(index)}"/>
        </p:column>
    </p:dataTable>
</h:form>

以及以下辅助 bean:

@ManagedBean
public class DFDemo {

    private List<Integer> indexes = Arrays.asList(1, 2, 3, 4, 5);

    public void openDialog(int index) {
        System.out.println("Opening a dialog for " + index);
        PrimeFaces.current().dialog().openDynamic("dfdemo", null, null);
    }

    // Getter & Setter
}

如果我点击第一个按钮,它会打开一个对话框并打印 Opening a dialog for 1。同样,如果我单击第二个按钮,它会打开另一个对话框并打印 Opening a dialog for 2.

按钮 1 和 2 现在不能再打开新对话框。它会在服务器上调用 openDynamic(),但不会打开任何内容。我认为它链接到其父级的原因是,如果您更改排序顺序并将索引 5 放在顶部,您仍然无法单击第一行(现在是按钮 5)。

我认为这是因为它链接到 rowIndex 以确保唯一 ID。我可以看到该按钮已使用 onclick='PrimeFaces.ab({s:"indexForm:indexTable:0:openDialogBtn"});return false;'.

重新呈现

不过我打算重新加载这个 table。这个table的内容会不一样,但是这个table的ID不会变。无法打开新对话框。

我尝试附加一些随机 ID 以确保在重新呈现 table 时的唯一性。但是附加我自己的 id 会导致组件中断(排序、操作...)。

我也无法使用具有特定区域更新的常规 Dialog 组件。因为它会破坏现有对话框的生命周期。

这似乎是对话框框架的默认行为。正如在 Dialog Framework showcase 中一样,无法从同一个按钮打开多个对话框。

是否可以让 Dialog Framework 从同一来源打开多个对话框,或者是否有解决此问题的方法?

要让 Dialog Framework 发挥作用,您需要注册适当的 ActionListener。配置的默认 ActionListenerorg.primefaces.application.DialogActionListener。在这个ActionListener中,源WidgetVar和源ClientId被放入FacesContext.

在我的例子中,提供一个将随机 UUID 作为源组件的自定义实现就足够了。这允许从激活 Dialog.

的按钮打开多个对话框

所以下面的监听器:

public class RandomSourceDialogActionListener implements ActionListener {

    private ActionListener base;

    public RandomSourceDialogActionListener(ActionListener base) {
        this.base = base;
    }

    @Override
    public void processAction(ActionEvent event) throws AbortProcessingException {
        Map<Object, Object> attrs = FacesContext.getCurrentInstance().getAttributes();
        attrs.put(Constants.DIALOG_FRAMEWORK.SOURCE_COMPONENT, UUID.randomUUID().toString());
        base.processAction(event);
    }
}

注册于faces-config.xml:

<application>
    <action-listener>my.application.RandomSourceDialogActionListener</action-listener>
    <navigation-handler>org.primefaces.application.DialogNavigationHandler</navigation-handler>
    <view-handler>org.primefaces.application.DialogViewHandler</view-handler>
</application>

注意:由于源组件不再为人所知,源组件不再正确处理dialogReturn等事件。另一方面,原来的 DialogActionHandler 似乎也没有在 DataTable 中处理这些事件。但是当只使用一个按钮时它可能会影响你。