How to get a dialog box above all items in a page with p:layout? [duplicate] - jsf

Maybe it's a dumb question, but in Primefaces's <p:dialog> there's property which called appendTo which described in manual as:
Appends the dialog to the element defined by the given search
expression.
I can't realize what it useful for?

From the PrimeFaces User Guide (currently p. 185):
Do not place dialog inside tables, containers likes divs with relative positioning or with nonvisible
overflow defined, in cases like these functionality might be broken. This is not a limitation
but a result of DOM model. For example dialog inside a layout unit, tabview, accordion are a
couple of examples. Same applies to confirmDialog as well.
You can overcome this by using appendTo="#(body)" and your dialog will be attached as a child of the <body> node.
One of the main dialog option is modal and you could quickly end up with your dialog behind the overlay if you are not using appendTo as shown below:
See also http://forum.primefaces.org/viewtopic.php?f=3&t=16504
Notes:
Before PrimeFaces 5.0, the attribute to set was appendToBody="true". This was changed for 5.0.
If your dialog contains some buttons don't forget to surround them by <h:form> (see Proper Construct for Primefaces Dialog)

The PrimeFaces docs are a bit sparse on this point. appendToBody / appendTo (before 5.0) solves (or tries to solve) a problem where a PrimeFaces component does not get the right z-Index, meaning it does not appear before or behind other elements the way it should. However, this feature is problematic because it can cause other problems like p:commandbutton action doesn't work inside p:dialog
tl;dr:
Do not use appendTo / appendToBody. Instead, Dialogs (along with ConfirmDialog and OverlayPanel) should always be at the root of the component hierarchy, as a direct descendant of <h:body>. This will make them work reliably. In that case using appendTo / appendToBody is unnecessary.
One good way to accomplish this is to have one (or multiple) separate XHTML files for these components ("dialogs.xhtml"), which then gets included in your main XHTML file or template (for example using <ui:include>). Another solution is to use a <ui:define> in combination with a <ui:insert> if you want the dialogs to remain in the XHTML file where they are used.
Read on for details :-)
The problem
Some PrimeFaces components (such as dialogs) should be be displayed on top of other elements.
For example:
If you use <p:dialog ...modal="true">, and make the dialog visible, you get a dialog in the foreground, appearing above the rest of the page, with the rest of the page covered by a transparent layer.
You can see this for example in the PF Showcase for dialogs (button "Modal").
Behind the scenes, i.e. in the page's DOM, two things happen:
a new <div> (the "modal overlay") is created at the end of the <body>. This div gets the CSS styles: z-index: 1000; position: absolute; opacity: .30;. This makes it transparent and covering the whole page, to get the "modal" effect.
the (existing, but invisible) div of the dialog itself is made visible, and gets the styling z-index: 1001; position:fixed;. Note the z-index is one larger than the modal overlay, thus the dialog appears above the overlay.
However, this does not always work. The reason for this is an aspect of CSS called the stacking context. The details are a bit complex, but basically it says that the z-index of a page element is only compared to other elements inside the same parent element. In particular, an element may appear behind another element even though it has a higher z-index, if the element with the high z-index is contained in an element with a lower z-index.
The short (safe) version is: To be certain that z-index works as expected, all concerned elements should be siblings in the DOM.
Now, in this particular situation, the modal overlay must be right at the top of the DOM hierarchy (i.e. inside <body>), otherwise it cannot reliably appear above the rest of the page. However, the div of the dialog itself is somewhere deeper in the DOM (corresponding to the position of the <p:dialog> tag in the source XHTML). Now we have a problem.
In practice, this means that the overlay may appear above the dialog, thus obscuring and blocking it. Similarly, if the dialog is not modal, it may appear behind other elements in the page.
The insidious thing about this problem is that it depends on the structure of the rest of the page (specifically, whether the rest of the page uses CSS that creates a new stacking context). So <p:dialog> may appear to work initially, then suddenly shows incorrectly after a change elsewhere.
How 'appendTo' helps
As explained above, the problem occurs because the HTML rendered for the PrimeFaces component is somewhere deep down in the DOM, while it would need to be a direct child of <body> for the z-index to work correctly.
When appendToBody / appendTo is used, PrimeFaces will include Javascript in the rendered page which simply moves the DOM node of the PrimeFaces component to the end of <body> (using JQuery's appendTo function). That way the component is in the right place in the DOM, and z-index works.
The problem with using 'appendTo'
While the DOM reorganization performed by appendTo solves the problem with CSS and z-index, it introduces another (potential) problem:
The client-side DOM no longer corresponds to the server-side page state maintained by JSF (called the view).
Now, one of the central features of JSF is that it expects the client-side HTML/DOM structure to correspond to the the server-side view - after all, JSF constructed the HTML from that view. If that rule is violated (usually by manipulating the DOM client-side), you get all kinds of weird problems, such as JSF ignoring form fields or values in a submit, or overwriting part of your modifications on AJAX updates.
In this case, the problems caused by moving the DOM node of the PrimeFaces component include:
If the PrimeFaces component is part of a <h:form>, it will not work properly (because it will not be inside the <form> tag client-side because of the moving).
This is actually mentioned in the PrimeFaces docs, along with the workaround: Instead of putting the component into a form, put a form inside the component - then the form will move with the component.
If the area where JSF originally rendered the PrimeFaces component is updated using JSF's AJAX feature, JSF will remove area to update from the DOM, then render the component again, as it does not know it was moved elsewhere.
In old versions of PrimeFaces, this caused the component to appear in the DOM twice (with the same id), which caused problems with later submits. This was fixed for PrimeFaces 4.0 ( Issue 5636: Dialog appendToBody & dynamic doesn't remove the old dom element ), but re-occurred in 5.0 (issue #367).
This shows that this kind of DOM manipulation "behind JSF's back" is rather risky and should be avoided - thus my advice to not use appendTo / appendToBody.

Related

Is there any insensitive to use rendered instead of jstl c:if?

Is there any reason not to use c:if over the rendered attribute? When I started learning jsf the general vibe I got from the tutorials I read was that jstl tags should be forgotten. So everytime I use a jstl tag I feel like I'm doing something wrong.
However for c:if, it is executed at build time while rendered jsf attribute is executed at rendering time (explanation here). It looks like a waste to me to add something to the component tree if it's not to be rendered afterwards. Better not adding it at all using c:if, amiright?
For example on a all my pages, I've an admin menu that is included if the user is admin. I see no reason to add the menu to the tree if it's not to display it when page is rendered. So I just use c:if there. I use rendered on small parts when it's more convenient or for ajax type things.

Can Primefaces dialog framework display xhtml from an external domain?

when I read about the Primefaces Dialog Framework (DF), which is "used to open an external xhtml page in a dialog", I assumed this meant you could display xhtml from another domain.
If this is the case, how can I give an absolute url to the method...
requestContext.getCurrentInstance().openDialog(outcome)?
These don't seem to resolve.
If this is not the case, then what is the purpose/advantage of the DF? If I can only display xhtml from within the same app, why not just use the declarative <p:dialog> component? It can be put inside a <ui:composition> if you want to reuse a dialog from multiple pages, for instance.
OpenDialog enables the page author to open an xhtml referenced via a JSF navigation outcome in a dialog, the options are the configuration attributes for dialog like modal, draggable and finally the optional params are the view params to pass parameters to the dialog.
Actually the PrimeFaces blog entry referring to that means to use an internal application view outcome for the dialog to refer to. That bounds the path to your application JSF navigation cases.
Then what's the advantage of the dialog framework? I would say, bringing you the ability to specify the outcome and the dialog attributes at runtime. Let's say you have a car table, where you open a detail dialog when user clicks on one row. Suposing you need to display different content depending on car's branch, it would be easy to control what is going to be rendered inside the dialog:
String outcome = "dialogs/genericCar";
if (car.getBranch.equals("Ferrari")){
outcome = "dialogs/ferrariCar";
}
else if (car.getBranch.equals("Aston Martin")){
outcome = "dialogs/astonCar";
}
RequestContext.getCurrentInstance().openDialog(outcome);
Doing that would be so clean an straight forwarded. Otherwise with the classing p:dialog tag you're limited to a single dialog with conditional rendering inside depending on the content you want to display.
The chance of being able to change the dialog attributes depending on what you want to render seems interesting too.
See also:
PrimeFaces Dialog Framework
Blog entry

Set X Y cordinates of compoenents in JSF

In Java, I can specify the location of a (for example) button somewhere in a panel. Is there an equivalent way of doing this in JSF?
Rephrasing the question:
For some type of panel (JSF component), can I specify the X and Y cordinates of where components in the panel should be placed?
I saw in PrimeFaces there is a Layout component. I was trying to add a button to it, but can not figure out a way to set the X and Y position.
In general JSF is not responsible for positioning components, it simply creates HTML markup. With "in Java" you propably mean a Swing-GUI and more specific the NullLayout (?).
The standard way of positioning components directly in HTML (which JSF generates) is via CSS stylesheets and the "position" property (example: http://www.w3schools.com/cssref/pr_class_position.asp).
You can put these positions into a separate CSS file or attach them directly to your JSF (or HTML) tags via the "style" attribute.
The layout tag from Primefaces tries to give you something like a LayoutManager in Java-Swing, whose main aim it is to avoid having to position things individually.
NOTE: As with a lot of HTML and CSS things, this may not work on every browser.

jsf popupwindow with a datatable

I have a form which one of it's fields is a code and description, also a button for opening a popup window that contains a list of all of the available codes.
when the user double clickes a row from that table i want to set these values to the code and description. - how can this be done?
Another question, I want to create this popup and table to be initialized dynamically - by that i mean that if i have a few forms in my application, when ever i have a field which has a description i want to be able to open this popup and to see the available list for that field. (every field can be from a diffrent table). is it possible to create something like that? if so, how?
Any help will be appritiated,
Thank's In Advance.
Yes, it is possible. Even more, many component libraries have ready to use popup/dialog components, such as RichFaces with <rich:popupPanel> and PrimeFaces with <p:dialog>.
If you do not want to use a component library for some reason, you would need to create a custom component for this which generates basically an absolutely positioned HTML <div> element with a CSS overlay which get shown/hidden by JS on a particular click/action. The HTML/CSS/JS part should be relatively simple if you are familiar with those languages. The JSF part is somewhat hard if you have never created a custom component before, but it should be possible with a composite component as well, so you could also just create one with pure XHTML. The updating/refreshing can just take place by the usual <f:ajax> means.

ExtJS 4 - Rendering components that are initially hidden

One major difference that I have noticed between ExtJS 3.x and 4.x is how the rendering/layout calculation is handled for components that are rendered inside of a containing element that has display:none (NOT an Ext created/monitored containing element). In 3.x, upon showing the containing element, the Ext component it contained would be properly rendered and sized to whatever dimensions i set for it.
However, in 4.x, that same component will not be displayed at all and have a zero height and width when its containing element was shown. After it was visible if I do a call to .setSize() it would then properly be displayed. Problem is, in my application there is just no way to be able to go through all the events that could cause a hidden component to be shown, and add code to make sure its layout is manually forced to be recalculated.
So my question is, is there any way to get back 3.x's behavior in this situation for all components across the board in 4.x?
What you can try to do is set up listeners on your components that delegate to the underlying DOM elements, perhaps that will solve your issue.
However my suggestion is if at all possible is to use the framework to manage the entire page layout using Viewport. You can still suck in the HTML (if you must) and render it inside containers or panels for example. Perfect use case here is Header and Footer which are generated by server side code (jsp, gsp, asp..) and then displayed in the North or South regions of the Viewport using contentEl : 'myDivId' configuration.

Resources