7

Is there a way to tell from the backing bean if a Primefaces Dialog is opened in the browser?

This is how I show a dialog on the facelet:

<p:menuitem value="Click me" oncomplete="dialogWidget.show();" />

When I look up the Dialog object from the ViewRoot, both dialog.isVisible() and dialog.isInView() returns true even though the dialog is not shown. Alternatively, is there a flag that tells me whether the main window is grayed out (this happens when a modal dialog is shown)?

Background info: I'm trying to figure out where to display my FacesMessages. My application can display messages in 2 locations: main window or in dialog pop-ups. When a modal dialog is in opened, I want the message to only display in the dialog. If there is no dialog shown, I want the message to display in the main window.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
citress
  • 889
  • 3
  • 13
  • 35

2 Answers2

5

Keeping track of dialog's status in a backing bean via listeners

You can keep dialog's open status as a boolean varable in you bean.

For this you can attach an actionListerer attribute of <p:menuItem> that will set the bean's boolean openStatus property to true. To switch that property back to false, essentially handling close, you can nest <p:ajax event="close" listener="#{dialogBean.dialogClosed}"> within your <p:dialog> with appropriately defined listeners.

The bean:

@ManagedBean
@ViewScoped
public class DialogBean implements Serializable {

    private boolean openStatus = false;//getter + setter

    public void dialogOpened(ActionEvent event) {
        openStatus = true;
    }

    public void dialogClosed(CloseEvent event) {
        openStatus = false;
    }

}

The view:

<h:form>
    <p:menu>
        <p:menuitem value="Open dialog" oncomplete="dialog.show();" update="dialogopen"/>
    </p:menu>
    <p:dialog widgetVar="dialog">
        <h:outputText value="This is your dialog"/>
        <p:ajax event="close" listener="#{dialogBean.dialogClosed}" update="dialogopen"/>
    </p:dialog>
    <h:outputText id="dialogopen" value="Is dialog open? #{dialogBean.openStatus}"/>
</h:form>

Updating bean property via <p:remoteCommand>

As far as dialogWidgetVar.show() and dialogWidgetVar.hide() are compeletely client side events, there state of a component doesn't include the "status of openness" of a dialog. As you can get from the primefaces documentation dialog.isVisible() gets the visible attribute of a <p:dialog>, which instructs to open the dialog on page load. As for dialog.isInView() method it simply checks if the component is present in the view, or not, and that also doesn't have any reference to the dialog's state you're after.

Also note that binding your dialog to a backing component variable of type org.primefaces.component.dialog.Dialog would give rise to the infamous issue.

Nonetheless, if you don't want to hook up extra listener to menuitem, your best bet is to use <p:remoteCommand>, that would do the update for you. Note, that close listener should be present so that the variable would be set back to false.

Modified bean:

@ManagedBean
@ViewScoped
public class DialogBean implements Serializable {

    private boolean openStatus = false;//getter + setter

    public void dialogClosed(CloseEvent event) {
        openStatus = false;
    }

}

Modified view:

<h:form>
    <p:menu>
        <p:menuitem value="Open dialog" oncomplete="dialog.show(); updateOpenStatus();"/>
    </p:menu>
    <p:dialog widgetVar="dialog">
        <h:outputText value="This is your dialog"/>
        <p:ajax event="close" listener="#{dialogBean.dialogClosed}" update="dialogopen"/>
    </p:dialog>
    <p:remoteCommand name="updateOpenStatus" update="dialogopen">
        <f:setPropertyActionListener value="#{true}" target="#{dialogBean.openStatus}"/>
    </p:remoteCommand>
    <h:outputText id="dialogopen" value="Is dialog open? #{dialogBean.openStatus}"/>
</h:form>
Community
  • 1
  • 1
skuntsel
  • 11,624
  • 11
  • 44
  • 67
  • Thanks, your solution would work. But I need to do this as transparently to the developers as possible, so if I can avoid having each developer call an actionlistener whenever a dialog is opened, that would be ideal. – citress Feb 28 '13 at 21:03
  • You can check out another solution which is probably what you're after. – skuntsel Mar 01 '13 at 08:26
  • Thanks for the detailed answer. I ended up going with pretty much the same approach, using a p:remoteCommand to update a backing bean property - id of the dialog in view (as I have multiple dialogs in the view) that is invoked on the dialog onShow and onHide properties. – citress Mar 05 '13 at 20:40
0

If you want to do it transparently for all developers you can create composite component that would do the job.

pepuch
  • 6,346
  • 7
  • 51
  • 84
  • If you think it is an answer, provide for a basic implementation of your vision. Otherwise just place it as a comment to the question. – skuntsel Mar 01 '13 at 09:20