Question

I need to show error and warning messages in a dialog when it is showing. If dialog is not showing I need to show the messages in the container page

I have set a template using facelets in all views: template="/WEB-INF/templates/template.xhtml"> with this content:

<f:view locale="#{loginBB.localeCode}">
    <p:messages autoUpdate="true" closable="true" id="globalMessages" />
    <ui:insert name="content" />
</f:view>

In all dialogs I have the following:

<p:messages autoUpdate="true" closable="true" id="dialogMessages" />

When a dialog is showing the error messages appear in the dialog and in the view that hold it, but I need that only appears in the dialog.

What I am doing wrong? I don't know what to do

EDIT: According to the BalusC answer I did the following:

Template:

<f:view locale="#{loginBB.localeCode}">
    <ui:insert name="dialogs" />
    <p:messages autoUpdate="true" closable="true" redisplay="false" />
    <ui:insert name="content" />
</f:view>

View:

<ui:define name="content">
    ...
</ui:define>

<ui:define name="dialogs">
    <h:form id="formX">
        <p:dialog ... >
        </p:dialog>
    </h:form>
</ui:define>

When the dialog is opened it show the message in the dialog. This is OK. But when the dialog is closed, it doesn't show the message in the main page

Was it helpful?

Solution

That gets tricky if the both <p:messages> components have an autoUpdate="true". It would be doable if only the page's <p:messages> is auto-updated. If you can ensure that the page's <p:messages> appears in JSF component tree after the dialog's <p:messages>, then it's a matter of setting the redisplay attribute of page's <p:messages> to false and making sure that each of the dialog's actions updates the dialog's own form with therein the <p:messages>.

<p:dialog>
    <h:form>
        <p:messages />
        ...
        <p:commandButton ... update="@form" />
    </h:form>
</p:dialog>
<p:messages autoUpdate="true" redisplay="false" />

No additional JS is necessary. You may only need to alter your templates to have an <ui:define name="dialogs"> above the page's <p:messages> so that all your dialogs end up there. Or, alternatively, use CSS to position the page's <p:messages> absolutely. Or, maybe, use JS to relocate the page's <p:messages> to there where you'd like to have it in HTML DOM.

OTHER TIPS

I have developed, lets say a "nasty" way.

page.xhtml

<p:dialog widgetVar="dialog" >
   <p:messages autoUpdate="true" />
</p:dialog>
<p:messages autoUpdate="true" />

page.js

$(document).ready(function() {
   /**
   * Hook onShow event
   */
   dialog.cfg.onShow = function onShowDialog() {
       $(".ui-messages").not('.ui-dialog .ui-messages').hide()
   }

   /**
   * Hook onHide event
   */
   dialog.cfg.onHide = function onHideDialog() {
       $(".ui-messages").not('.ui-dialog .ui-messages').show()
   }

})

OR if you want to apply this on all the dialogs.

But you MUST NOT define any widgetVar attribute for any dialog you have.

$(document).ready(function() {
   $('.ui-dialog').each(function() {
       widgetName = 'widget_' + $(this).attr('id').replace(/\:/g, '_');
       dialog = window[widgetName];

       dialog.cfg.onShow = function onShowDialog() {
           $(".ui-messages").not('.ui-dialog .ui-messages').hide()
       }

       dialog.cfg.onHide = function onHideDialog() {
           $(".ui-messages").not('.ui-dialog .ui-messages').show()
       }
   })
})

and the magic happens.


Note: if you update the dialog, you would lose the events, you need to re-run the script.


demo

I think that is not possible when you render the whole page, because every <p:messages/> tag will display the message.

But you could update dialog messages via ajax and render only that part of page, so the global messages wont be rendered again.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top