Is there a way to make a graphicimage in Primefaces execute the "value" method only on demand? - jsf

I want to show a custom gallery with several thumbnails. When clicking on one of these, an overlaypanel is shown, containing a graphicimage with the image in higher quality. Since the high quality images are aroung 5MB each, I just want to load them on demand.
I already tried using the "rendered" attribute, but that did not seem to do the trick either. I also tried the "onclick" with a javascript function, but that also did not yield the expected result.
<p:graphicImage value="#{dataHolderBean.imageHolderBean.loadFullSizeImage()}"
class="centeredImageOverlay" cache="false">
<f:param name="currentImageId" value="#{images.imageId}" />
</p:graphicImage>
I would like to just call value="#{dataHolderBean.imageHolderBean.loadFullSizeImage()}" this method, when clicking on another image.

Why did you not look for a solution that loads the content of the overlay panel lazy? That to me sounds like a much more generic solution (anything inside it would be loaded lazy then) you stand and a higher chance of something already being implemented.
From the PrimeFaces showcase of the p:overlayPanel(emphasis mine)
Overlay Panel
OverlayPanel is a generic container component that can overlay other
components on page. Notable features are custom positioning,
configurable events and effects. Lazy content loading to reduce page
load time is also supported via dynamic option, when enabled
overlayPanel will load the contents just before being shown.
From the PrimeFaces documentation
Dynamic Mode
Dynamic mode enables lazy loading of the content, in this
mode content of the panel is not rendered on page load and loaded just
before panel is shown. Also content is cached so consecutive displays
do not load the content again. This feature is useful to reduce the
page size and reduce page load time.
So the lazy loading is done via the dynamic attribute which has an example even in the showcase
<p:commandButton id="movieBtn" value="Dynamic" type="button" />
<p:overlayPanel id="moviePanel" for="movieBtn" hideEffect="fade" dynamic="true" style="width:600px" modal="true">
...
</p:overlayPanel>

You can use the built-in LazyDefaultStreamedContent in your bean, to lazy initialize the stream:
streamedContent = new LazyDefaultStreamedContent("application/vnd.ms-excel", "myExcel") {
#Override
protected InputStream initStream()
{
return new FileInputStream(...);
}
};

Related

JSF Primefaces load ResultSet directly to <p:dataTable> [duplicate]

Is there a way to decrease the load time of the page in IE just by using Data tables.
If we use server side pagination and sorting, can we also do a quick search on server side and also render only that particular tab instead of the whole page.
<h:panelGroup id="transactionsPanel">
<h:dataTable>
</h:dataTable>
<ui:repeat value="#{backing.pages}" var="page" varStatus="current">
<h:commandLink value="#{page}" actionListener="#{backing.page}"
rendered="#{page != backing.currentPage}" >
<f:ajax render="transactionsPanel"/>
</h:commandLink>
<ui:repeat>
</h:panelGroup>
The listener is called but the page is not updated to display the next page clicked.
Is there a way to decrease the load time of the page in IE just by using Data tables.
No.
At least, not without replacing IE by a more sane webbrowser. IE is known to have a poor HTML <table> renderer. This is a client problem, not a server (JSF) problem. You can confirm this by measuring the network traffic speed and browser HTML rendering speed.
If we use server side pagination and sorting, can we also do a quick search on server side and also render only that particular tab instead of the whole page.
Just perform the search (by ajax) in server side as well.
I recommend to look at JSF component libraries instead of grabbing to loose jQuery plugins and cobbling loose scripts together. PrimeFaces for example has a lazily loadable <p:dataTable> which solves all your problems with just clean XHTML and JPA. See also the lazy <p:dataTable> showcase example and Efficient JSF Pagination.

Want to lazy load panel data in jsf application

I have numerous AccordionPanel in my jsf page.
<p:accordionPanel multiple="true" id="HomeAddress">
so everytime we add new accordion panel and load the page, it is taking long time to load all the panel.So I want to lazy load the panels. At first load five panel and once we scroll to the end it will load rest of the panels. Something like happening in all e-commerce site (Flipkart, Amazon etc..)
An accordionPanel is one componenent and like most complex PF components, it does not allow updating one of it's children or dynamicaly adding one (tabs in this case). And dynamicaly loading is an even different thing. You can achieve this by adding an
<p:outputPanel deferred="true" deferredMode="visible">...
</p:outputPanel>
inside each tab and put the content in there. But adding a tab to the accordionpanel will still reload all tabs, lazy, ok, but still reload them when accessed

Render a jsf element on mouseover

I have a <h:panelGrid> and a h:commandLink(link is basically a image).Now I want that on mouseover event , Then link should be render(render='true') and on mouseout event, it gets removed render='false'.But I am unable to create the logic that How can I do this with these events as the approach I am using is To set the values of bean true and false on this event.
Here is my code
<h:form>
<h:panelGrid mouseover='** we cannot call a bean method here which changes the bean value **'>
This is the Div On which I want to apply mouseover event
</h:panelGrid>
<h:commandLink id="btn" render={renderBean.renderLink}>
<h:graphicImage url="image.jpg"/>
</h:commandLink>
</h:form>
The default value of renderLink attribute of renderBean is false. Now I want to know the way that How can I change its value to true on mouseover event? Is it possible? OR Anyother solution in JSF w.r.t this requirement
You have to remember in JSF that the page will first be processed server-side by the JSF engine in the web server. At that time all JSF tags will be converted into their HTML equivalent. The render attribute tells the server-side engine whether or not to output an HTML a (anchor) link in the place of the <h:commandLink> element.
The behavior you're looking for, namely responding to mouse events, is client-side functionality. It happens in the browser, not at the web server, so no JSF is involved. The solution is to handle the mouse events in JavaScript, not JSF. You will typically set (or remove) the CSS attribute display:none on the id called btn (unfortunately it's slightly more complex as JSF will mangle the element id a bit). There are lots of posts here on StackOverflow that deal with how to handle client-side events in JavaScript. Using jQuery for example is a really common approach.
I recommend to get started you take a look at the blog of one of our best JSF resources and long-time StackOverflow user BalusC: http://balusc.blogspot.com.
There's a lot to learn and you'll get a good start by going there first (and searching for his posts on SO).
Good luck.

JSF 2.0: Preserving component state across multiple views

The web application I am developing using MyFaces 2.0.3 / PrimeFaces 2.2RC2 is divided into a content and a navigation area. In the navigation area, which is included into multiple pages using templating (i.e. <ui:define>), there are some widgets (e.g. a navigation tree, collapsible panels etc.) of which I want to preserve the component state across views.
For example, let's say I am on the home page. When I navigate to a product details page by clicking on a product in the navigation tree, my Java code triggers a redirect using
navigationHandler.handleNavigation(context, null,
"/detailspage.jsf?faces-redirect=true")
Another way of getting to that details page would be by directly clicking on a product teaser that is shown on the home page. The corresponding <h:link> would lead us to the details page.
In both cases, the expansion state of my navigation tree (a PrimeFaces tree component) and my collapsible panels is lost. I understand this is because the redirect / h:link results in the creation of a new view.
What is the best way of dealing with this? I am already using MyFaces Orchestra in my project along with its conversation scope, but I am not sure if this is of any help here (since I'd have to bind the expansion/collapsed state of the widgets to a backing bean... but as far as I know, this is not possible). Is there a way of telling JSF which component states to propagate to the next view, assuming that the same component exists in that view?
I guess I could need a pointer into the right direction here. Thanks!
Update 1: I just tried binding the panels and the tree to a session-scoped bean, but this seems to have no effect. Also, I guess I would have to bind all child components (if any) manually, so this doesn't seem like the way to go.
Update 2: Binding UI components to non-request scoped beans is not a good idea (see link I posted in a comment below). If there is no easier approach, I might have to proceed as follows:
When a panel is collapsed or the tree is expanded, save the current state in a session-scoped backing bean (!= the UI component itself)
The components' states are stored in a map. The map key is the component's (hopefully) unique, relative ID. I cannot use the whole absolute component path here, since the IDs of the parent naming containers might change if the view changes, assuming these IDs are generated programmatically.
As soon as a new view gets constructed, retrieve the components' states from the map and apply them to the components. For example, in case of the panels, I can set the collapsed attribute to a value retrieved from my session-scoped backing bean.
Update 3: I got it working as described above. To sum it up, the solution is to store the relevant properties in a session-scoped bean instead of making the entire UIComponent session-scoped. Then, when the component is re-constructed after navigation has occurred, set the attribute values by retrieving the saved properties (using EL), e.g.
<p:panel collapsed="#{backingBean.collapsedState}" ... />
(This is a simplified example. Since I am using multiple panels, I am using a map to store these properties, as described above).
One solution would be to use session-scoped beans.
What do you mean by collapsible panels? I ask because there is a component that is closable as well as a component. I am using in the navigation pane in my project. The accordianPanel has an attribute named "activeIndex". Here's what I did in my sessionBean to maintain the state of my accordion tabs:
private int tabIndex; //declared a private variable
public SessionBean() {
tabIndex = 100; //set the initial tab index to 100 so all tabs are closed when page loads.
}
public int getTabIndex(){
return tabIndex;
}
public void setTabIndex(int tabIndex){
this.tabIndex=tabIndex;
}
in my navigation pane:
<p:accordionPanel activeIndex="#{sessionBean.tabIndex}" collapsible="true" autoHeight="false">
<p:tab title="#{tab1_title}">
<h:commandLink value="link here" action="target_page?faces-redirect=true" /><br/>
</p:tab>
<p:tab title="#{tab2_title}">
<h:commandLink value="link here" action="target_page?faces-redirect=true" />
</p:tab>
<p:tab title="#{tab3_title}">
<h:commandLink value="link here" action="target_page?faces-redirect=true" />
</p:tab>
</p:accordionPanel>
I'm not using the tree component for navigation as that presented my project with some difficulties that were easily overcome by using the accordionPanel, so I can't speak to that part of your navigation.

How to Refresh only components in certain 'box'

Say I have a websites with 3 panel grid (just for example..) and I would like to have buttons inside each grid that only cause the contents of that grid to refresh so the rest of the page doesn't necessarily have to refresh.
How do I do that?
I tried to have a form sorround that grid but it seems like the rest of the page still gets refreshed.
A Note - I'm trying to achieve something like what happens when you work with a picklist. when you move the objects between the lists there doesn't seem to be any page refresh...
Thanks!
If you are using RichFaces, you should definitivly check the Ajax chapter of the RichFaces manual. I think you will find everything you need to know there.
Here a small example for partial page rendering:
<a4j:commandButton value="update" reRender="infoBlock"/>
<h:panelGrid id="infoBlock">
<!-- Some content-->
</h:panelGrid>

Resources