Reputation: 1575
With PrimeFaces, I'd like to open multiple different dialogs. An easy way at first seems the PrimeFaces Dialog Framework. Which does work to an extent.
I have a DataTable
with records, each record can be opened into a new Dialog
. For each record, opening this dialog works fine. But it seems that the Dialog
seems to be bound to the id of its invoking parent.
A minimal example to demonstrate this issue is the following. Consider the following 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>
And the following backing 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
}
If I click on the first button, it opens a dialog and prints Opening a dialog for 1
. Similarly, if I click the second button, it opens another dialog and prints Opening a dialog for 2
.
Buttons 1 and 2 are now no longer able to open a new dialog. It does call openDynamic()
on the server, but doesn't open anything. The reason I think it's linked to its parent, is because if you change the sort order and put index 5 on top, you can still not click the first row (now button 5).
I assume this is because it's linked to the rowIndex
to ensure a unique ID. I can see the button is re-rendered with the onclick='PrimeFaces.ab({s:"indexForm:indexTable:0:openDialogBtn"});return false;'
.
I intend to reload this table however. The contents of this table will be different, but the IDs of this table won't change. Making it impossible to open a new dialog.
I tried to append some random id to ensure uniqueness when re-rendering the table. But appending my own id causes the components to break (sorting, actions, ...).
I couldn't use the regular Dialog
component with specific zone updates neither. Because it would ruin the lifecycle of the existing dialogs.
This does seem to be the default behavior of the Dialog Framework. Just as in the Dialog Framework showcase, it is not possible to open multiple dialogs from the same button.
Is it possible to have the Dialog Framework open multiple dialogs from the same source or is there a way to work around this issue?
Upvotes: 1
Views: 1214
Reputation: 1575
To have the Dialog Framework
do its thing, you need to register the appropriate ActionListener
. The default ActionListener
that is configured, is the org.primefaces.application.DialogActionListener
. In this ActionListener
, the source WidgetVar
and source ClientId
are put into the FacesContext
.
In my case, it was sufficient to provide a custom implementation which puts a random UUID as the source component. This allowed multiple dialogs to be opened from the button which activates the Dialog
.
So the following listener:
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);
}
}
Is registered in the 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>
Note: Since the source component is no longer known, events such as dialogReturn
are no longer handled correctly by the source component. On the other hand, the original DialogActionHandler
doesn't seem to handle these events in a DataTable
neither. But it might affect you when using only a single button.
Upvotes: 2