4

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

John Alexander Betts
  • 4,718
  • 8
  • 47
  • 72

3 Answers3

3

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Right, that indeed doesn't work if the dialog's `` has also an `autoUpdate="true"`. Is it acceptable to just put it inside a form and perform `update="@form"` in any of the dialog's commands? Perhaps you already have those? I've updated the answer. – BalusC Apr 15 '14 at 18:23
  • Ok, it fix the problem, but when I press the commandButton it closes my dialog – John Alexander Betts Apr 15 '14 at 18:43
  • 1
    This is actually a separate problem and not the standard behavior. Perhaps you've a `dialogWidgetVar.hide()` in `oncomplete` or so? Or you actually placed the form outside the dialog? – BalusC Apr 15 '14 at 18:45
  • I don't have a dialogWidgetVar.hide() in oncomplete attribute but I placed the form outside the dialog – John Alexander Betts Apr 15 '14 at 18:47
  • 1
    Form must always go inside the dialog, not only for this reason, but also to avoid failing synchronous submits because the dialog is by default by JS relocated to end of the body. – BalusC Apr 15 '14 at 18:48
  • That's all. Tomorrow I will give you your 50 points. Thanks... The great BalusC – John Alexander Betts Apr 15 '14 at 18:50
  • When the dialogs are not showing chrome put a blank space where they must appear. Do you know what I can do? – John Alexander Betts Apr 22 '14 at 13:32
  • 1
    Shouldn't happen. Did you alter the PrimeFaces dialog CSS? Otherwise try if `` works for your specific problem. If in vain, show an SSCCE. – BalusC Apr 22 '14 at 13:39
  • Excellent. As always, you are the greatest one – John Alexander Betts Apr 22 '14 at 13:45
  • Just in case, primefaces suggests the use of appendTo="@(body)" instead of appendToBody="true" because the last one will be deprecated – John Alexander Betts Apr 22 '14 at 14:02
  • Excuse me, in safari, dialogs are showing at the bottom of the page, in iPads I need to scroll down to view the dialog – John Alexander Betts Apr 22 '14 at 21:12
  • Did you alter the PrimeFaces dialog CSS? That might also explain the blank space which you shouldn't be seeing in first place. – BalusC Apr 23 '14 at 06:16
  • This is the CSS that I have changed: .ui-dialog { position: absolute; } .disable-scroll .ui-dialog-content { overflow: hidden; width: auto; } – John Alexander Betts Apr 23 '14 at 14:20
1

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

Hatem Alimam
  • 9,968
  • 4
  • 44
  • 56
  • Well, since you have two rendered messages in the same time (one in the main, and another in the dialog) this is the only way of hiding while the dialog is opened... at least for me :) – Hatem Alimam Dec 18 '13 at 14:06
  • It doesn't work. Id doesn't regonize the dialog variable. Could you give me please the code of the demo you posted here? – John Alexander Betts Apr 15 '14 at 15:53
0

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.

britulin
  • 310
  • 2
  • 4
  • How can I do that? Please – John Alexander Betts Dec 17 '13 at 21:38
  • Let's say you have h:commandButton that executes some logic from your bean class. In order to do it the ajax way, the code should look like this. ` ` You can also use `` instead of ``, and then you use attribute render instead of update, and with no commas between component id's. – britulin Dec 17 '13 at 21:52
  • Are the dialogMessages component and button that executes the action in the same form? If so, you can try with update="@form". If not, maybe you don't reference it right. See this answer for help - [How to reference components in JSF ajax? Cannot find component with identifier “foo” in view](http://stackoverflow.com/a/8644762/1746808) – britulin Dec 18 '13 at 18:48
  • Yes, they are in the same form – John Alexander Betts Dec 18 '13 at 21:11
  • Then it should work with `` . Did you try that? – britulin Dec 18 '13 at 22:04