0

I am trying to change the p:growl position of primefaces through the .ui-growl class to use position: sticky. However, since the component is rendered at the end in body, the relative behavior of the position does not work as I would like.

Is there any way to use the sticky position for this component? Or some way to get the component to render where it is declared?

PrimeFaces 5.1; Mojarra 2.1;

Edu Müller
  • 435
  • 2
  • 5
  • 19
  • What do you want to achieve? What is not correct in the default growl behaviour? – Kukeltje Aug 02 '19 at 21:21
  • When the scroll is at the top of the screen, I don't want the growl to be displayed at the top of the screen, I want it to be displayed about 65 pixels from the top. But when the scroll is scrolled, it's about 10 pixels from the top. The behavior of the CSS `position: sticky` property. – Edu Müller Aug 03 '19 at 11:26

1 Answers1

2

Disclamer: I tried this with the PF 7.0 showcase, but I think the basics also work with the 5.1 version.

You effectively have 4 options. The latter three all need you to inspect the javascript source of the component (which is open, so you can ALWAYS inspect it before asking questions, the java source is irrelevant here) and for the first solution it helps to see how the component works, but inspecting with a browser developer tool is sufficient (that is how I did it).

Basic analysis with or without looking at the source

This is a variant on your "Or some way to get the component to render where it is declared?". Since on the client side, it is all plain html, css and javascript, you can manipulate with al tools available on the client-side.

You can see that the main part of the grow is html technically rendered where it is declared. Check the PrimeFaces showcase and you'll see

<span id="j_idt700:growl" class="ui-growl-pl" data-widget="widget_j_idt700_growl" data-summary="data-summary" data-detail="data-detail" data-severity="all,error" data-redisplay="true"></span>

right inside the form where it also is in the xhtml. The javascript of the component creates the client side dom things, amongst which is the container that you see right before the end of the body (from the showcase)

<div id="j_idt700:growl_container" class="ui-growl ui-widget" style="z-index: 1002;"></div>

This last piece is html is where the individual growls are added to when they need to be rendered and hence the part that makes the component in most normal cases behave correctly but needs to be done differently in your case.

Solution 1, pure client-side component agnostic solution

Effectively this is as simple as moving this piece of html in the dom, see How to move an element into another element?.

In the online showcase I put the following jquery code in the browser developer tool console

$("#j_idt700\\:growl_container").prependTo(".layout-content");

And added the following css

position: sticky;
top: 10px;
float: right; // this is needed in the showcase, might not always be needed

And it worked.

The jquery should be put somewhere in your page where it runs after the component javascript is executed, so best is to do it right before the end of the body. Keep in mind that the j_idt700 prefix is the dynamic id of the form in the showcase (it does not have a fixed id here), but you can also use different selectors based on the classes or whatever)

Solution 2, changing the source 'locally'

In the javascript source, you can see where the container is technically rendered

render: function() {
    //create container
    this.jq = $('<div id="' + this.id + '_container" class="ui-growl ui-widget"></div>');
    this.jq.appendTo($(document.body));

    //render messages
    this.show(this.cfg.msgs);
},

Changing the this.jq.appendTo($(document.body)); in some way to have it appended to the current html node ('this'?) will make it work too. Regarding the overriding, you have two options

Solution 3 Changing the source server side

Effectively you do the first part of #2 but patch the source and create a new custom PrimeFaces version

Solution 4 Make this feature avaiable for others too

What can be done here is to create a new attribute on the component and patch the source in some places so it is configurable to have the component behave as it is now or as sticky (they changed the existing 'sticky' attribute to 'keepAlive' in 7.0.x so sticky is avalable again ;-)). Of course this should be submitted as a patch then...

Community
  • 1
  • 1
Kukeltje
  • 12,223
  • 4
  • 24
  • 47
  • Thank you so much for your answer. I had started looking at growl.js and was intent on somehow solving its solution 3, or using `p:messages` with some changes to the style classes (also because, in version 5.1, growl did not offers style classes for message severity). Of course I like solution 4 better, but I think for the moment I will opt for option 1. ;) – Edu Müller Aug 03 '19 at 13:57
  • 2 is the 'in between' ;-) That is always possible with all components (the client-side parts) – Kukeltje Aug 03 '19 at 13:59
  • @Kukeltje Off topic: did you either hear that bang of the [fireball](https://fireballs.imo.net/members/imo_view/event/2019/4385) yesterday 14:50? Looks like many ppl in NL recognized it. – Selaron Sep 13 '19 at 06:51
  • @Selaron: no, was in a product meeting (web based edifact, vmi, gdsn) ... deep down in some dungeon ;-) – Kukeltje Sep 13 '19 at 19:45