ExtJS 4 - Rendering components that are initially hidden - layout

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.

Related

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

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.

JavaFX-8: Custom Layout and Layout Passes (layout pass/css pass): Where should I add child nodes?

I'm developing a custom table component for very large and very custom content. Therefore I decided not to go with TableView, but start from scratch (i.e. Control). I adopted the idea of the VirtualFlow to create and manage only the visible part of the table and reuse cells that have become invisible. However I needed virtual rows and columns.
My CustomVirtualFlow implements layoutChildren(). From the component's size and scrollbar positions I know which cells are visible. If necessary, I add cells to the VirtualFlow. I then update the content and css pseudo class states (selected, focused, ...).
This works almost fine ... currently, my only problem is that the css styles are sometimes lagging: newly created cells are shown with e.g. wrong backgrounds for a moment and then get correcteted with the next pulse.
My explanation for this is that JavaFX performs layout in two passes:
first a css pass and secondly the layout pass that calls layoutChildren().
The css of newly added children (during layoutChildren) is therefore not processes correctly.
I tried to call applyCss() directly, which helps, but seems to do too much because it takes a lot of time.
My question is:
How is the correct way to add nodes during layout, i.e. if the size of the component makes it neccessary to use further nodes?
If it is not during layoutChildren(), where else should I do it?

Xpages add a custom control that doesn't take up space (rendered versus loaded versus visible)

I have some custom controls that I want to include in Xpages, but I don't want them to be visible to the user or to take up space on the screen, as it is throwing my alignment off. I have looked at the properties rendered, loaded, and visible, but I don't really understand them and they don't seem to do what I want, which is to include some functionality but not change the layout.
I am sure there is a way to do this, but I can't figure it out.
Loaded means it won't be added to the component tree and only affects server-side functionality. Because it's not in the component tree (the server-side map of the page) it can't be passed to the browser or processed during partial refreshes. Rendered and visible are the same and mean they're in the component tree, so server-side processing can interact with them, but no HTML is passed to the browser for them. So you can't interact with them via CSJS. If you want it passed to the browser, available for CSJS but not visible to the user, you'll need to set the style as display:none. Another option is to put that style in a theme and allocate the themeId you choose to your custom control.

ExtJS 3.4 EditorGridPanel Layout Issues

GridPanel not rendering correctly
I'm using EditorGridPanels on dynamically generated web pages. ExtJS does not control the ViewPort.
When I wrap the Grid generation code in Ext.onReady(), the grids render perfectly.
If I do not wrap it in Ext.onReady() it renders with subtle layout issues like
the grids are a little too wide
the top toolbar gets cut off on the right
the rows don't quite fit and they shift when clicking a cell
I have tried forcing the grids' layout to get recalculated once the page loads...
(function(){}
var grid = ...
[ ... ]
Ext.onReady(function(){
grid.doLayout();
});
)();
...but this does not work.
The reason I'm trying to avoid placing Grid initialization inside Ext.onReady() is that sometimes pages take a long time to fully load every resource, and in these cases the pages look fully loaded apart from the blank spaces where the grids eventually get rendered to!
Any suggestions on what I might try? Right now a complete redesign of the page is not in scope, so I'm looking for something I can do to get the grid to layout like it does when initialized inside onReady()!
Thanks
You could perhaps mask the page initially with 'loading..' message and remove this in the onReady().
If you're getting issue outside of on the onReady it would indicate something has not loaded when you're trying to render components, this in my experience will lead to further issues down the line.

JSF2 LogicalViews - Losing the Current Page From the Map

We recently updated our Application to use JSF 2.1.3
We have an existing page that has three framesets (left nav, main, footer). Clicking on something in the main frame, causes the footer frame to be reloaded with new content. Because of this, we are losing the main frame from the logical view map after (eg. if com.sun.faces.numberOfLogicalViews is set to 10, we lose the main frame after 9 clicks). After which, trying to submit the main frame causes it to re-render, skipping the action method it's bound too.
Is there any way to keep that logical view from being removed from the map without increasing the number of logical views? I'm not sure why, but this behavior didn't occur when out app was using JSF 1.2.
We solved this problem by overriding the StateManagerImpl, and storing this particular view client side, instead of server side.
It appears in previous versions of jsf, you only needed to override the isClientSide method, but you now need to override the methods to write and restore state.

Resources