0

I'm having an odd problem with Notification bar in Primefaces. Actually, Notification bar itself displays on page load without problems, and buttons for open/hide work fine.

Problem is in JavaScript call for hiding Notification bar - it doesnt work. It doesn't work even if I exclude setTimeout and call hide function directly. Situation is same even with button for displaying Bar - button works, but it is not working from JavaScript.

And I checked, if I put alert in JavaScript it displays without problems, so functions are working.

Any ideas?

Thanks!

    <h:form>

        ...

        <p:notificationBar position="top" effect="slide" 
                  styleClass="top" widgetVar="bar" autoDisplay="true">

           <p:commandButton id="barOff" onclick="PF('bar').hide()" 
                  type="button" icon="ui-icon-arrow-1-n"/>
           <h:outputText value="Some text" style="font-size:36px;" />

        </p:notificationBar>

        <p:commandButton id="barOn" value="Show" onclick="PF('bar').show()" 
                  type="button" icon="ui-icon-arrow-1-s"/>

     </h:form>


     <script type="text/javascript">

        function load() {
            setTimeout(close(), 3000);
        }

        function close() {
            document.getElementById('barOff').click();
        }

        document.getElementsByTagName('body')[0].onload = load();
    </script>

2 Answers2

0

barOn and barOff <p:commandButton> are in a naming container, so in order to select them, you have to either:

  • prefix their id with the naming container id
  • add prependId="false" to the naming container (see note below)

Edit: note about component ids and UINamingContainer From BalusC's blog:

Render IDs are resolved relative to the parent UINamingContainer component. Examples of UINamingContainer components are <h:form>, <h:dataTable>, <ui:repeat>, etc. It are those components which prepends the client ID of their children with its own client ID.

[...]

The absolute render ID needs to be the full client ID prefixed with ":". So if the render target is by itself nested in another UINamingContainer component, then you need to give it a fixed ID and include its ID as well.

When using prependId="false" on a UINamingContainer, the ID of components inside it is rendered as-is in the DOM. This is somehow an easy way out that should be avoided since it can lead easily to have accidentally multiple components with the same ID in the DOM. It is better to use fully-qualified IDs.

Taking this precaution into account, just add an id to the form and use it as prefix to qualify its children components:

<h:form id="notification-form">

and

function close() {
   document.getElementById('notification-form:barOff').click();
}

or simply (without the need to reference IDs):

function close() {
   PF('bar').hide();
}

See also:

UIForm with prependId="false" breaks <f:ajax render>

Community
  • 1
  • 1
Zim
  • 1,457
  • 1
  • 10
  • 21
  • 1
    Never recommend `prependId="false"` to starters without explaining its side effects. – BalusC Jun 15 '15 at 07:53
  • http://stackoverflow.com/questions/7415230/jsf-namingcontainer-and-uiform-with-prependid is a better one. – BalusC Jun 15 '15 at 08:25
  • Well I tried prefixing and it doesn't work. Form's id is `form`, so I write `PF(':form:bar').show();` and `PF('form:bar').show();` and `PF('bar').show();` and none of them is working. Am I making some kind of mistake. I even tried prependId (just for the test, I don't mean to use it) and it also doesn't work. – markickale Jun 15 '15 at 08:53
  • `PF()` function expects a Primefaces component `widgetVar`. Anyway, `PF('bar')` should work. Does your browser's console tell anything on page load? It's time to start debugging with steps such as `onload="console.log(PF('bar'))"` – Zim Jun 15 '15 at 10:34
  • Thanks @Zim, console.log helped me to find root of the problem. It is contected with setTimeout(). I posted an answer. – markickale Jun 16 '15 at 08:21
0

After working with console.log() as @Zim proposed, I founded that notification bar isn't available at the moment of the page load - I was getting undefined object. After making a delay with setTimeout(), Notification bar started opening. That delay could be as small as 10ms, or even less. It even worked with values like 1ms, or even 0! Now, Notification bar opens perfectly.

Here is modified code that works as expected:

<h:form id="forma">

    ...

    <p:notificationBar position="top" effect="slide"
                   styleClass="top" widgetVar="bar">

        <p:commandButton id="barOff" onclick="PF('bar').hide()" 
                         type="button" icon="ui-icon-arrow-1-n"/>

        <h:outputText value="Text!" style="font-size:36px;" />

   </p:notificationBar>


   <p:commandButton id="barOn" value="Show" onclick="PF('bar').show()" 
                  type="button" icon="ui-icon-arrow-1-s"/>

</h:form>

<script type="text/javascript">

        function load() {
            setTimeout(function() { open(); }, 10);
        }

        function open() {
            PF('bar').show();
            setTimeout(function() { close(); }, 6000);
        }

        function close() {
            PF('bar').hide();
        }

       document.getElementsByTagName('body')[0].onload = load();

</script>
  • _In fine_, what I don't get is why doing all this Javascript initialization? If you want the `` to be displayed on page load, add `autoDisplay="true"` as you did in your original post. Otherwise set it to `false` (or don't set it). – Zim Jun 16 '15 at 08:50
  • I understand that, but I wanted to be able to open Notification bar not right after page loads, but after number of seconds. I could add `autoDisplay="true"` and remove "open bar" part from JavaScript, but that would display bar directly after page load. – markickale Jun 16 '15 at 09:06
  • OK, if you need a deferred opening, that makes sense :) – Zim Jun 16 '15 at 09:23