I have a JSF page that loads the properties of an object (for which the id is passed in the URL). The loading can last more seconds, so I would like to display a wait/busy indicator or a "Loading..." message.
This is done using "viewAction"
<f:metadata>
<f:viewAction action="#{myBean.loadParams}" />
</f:metadata>
Is there a simple way to accomplish this goal? I'm using Primefaces.
PrimeFaces has already a component ready for that: the <p:outputPanel deferred="true">
. You only need to make sure that the #{heavyBean}
is only referenced in a component (and thus definitely not in a tagfile like <c:xxx>
for the reasons explained here) within the <p:outputPanel>
and not somewhere else.
...
#{notHeavyBean.property}
...
<p:outputPanel deferred="true">
...
#{heavyBean.property}
...
</p:outputPanel>
...
#{anotherNotHeavyBean.property}
...
Then you can do the heavy job in its @PostConstruct
method. Do the job you originally did in <f:viewAction>
there in the @PostConstruct
.
@Named
@ViewScoped
public class HeavyBean implements Serializable {
@PostConstruct
public void init() {
// Heavy job here.
}
// ...
}
If you need to access properties of other beans, simply @Inject
those beans in the HeavyBean
. E.g. in case you needed the ID view param:
<f:viewParam name="id" value="#{notHeavyBean.id}" />
@Inject
private NotHeavyBean notHeavyBean; // Also @ViewScoped.
@PostConstruct
public void init() {
Long id = notHeavyBean.getId();
// Heavy job here.
}
The <p:outputPanel>
already comes with an animated gif. You can easily customize it via CSS.
.ui-outputpanel-loading {
background-image: url("another.gif");
}