I had the same Problem this was my Solution (not super simple but very flexible):
If you want to add an Loading Indikator for some Part of the Page you need to add two <h:panelGroup>
Elements, one for the loading Indicator and one for the loaded Content.
e.g.:
<h:panelGroup styleClass="contentPreview content">
<h:outputText id="previewText" styleClass="updatePreview" value="#{lazyResultBean.previewContent}" />
</h:panelGroup>
<h:panelGroup styleClass="contentPreview loading">
<p:graphicImage style="width: 15px; height: 15px;" name="/images/ajax-loader.gif" />
</h:panelGroup>
Important is to set the correct styleClass's loading
for the Loading Indicator and content
for the content.
Both Panels also need to have a class which they share, in this case the contentPreview
Class.
To switch between loading Indicator and Content you just need to call a JavaScript Function.
showLoading('.contentPreview')
to show the Loading Indicator
hideLoading('.contentPreview')
to hide the Indicator and show the content.
e.g.:
<p:commandButton id="previewBtn" onstart="showLoading('.contentPreview')" oncomplete="hideLoading('.contentPreview')" value="Preview" update="previewText" actionListener="#{lazyResultBean.loadPreviewContent(result.url)}">
</p:commandButton>
The code for the JavaScript Functions looks as follows:
function showLoading(clazz) {
console.log('showLoading' + clazz);
var loadingElements = $(clazz + '.loading');
loadingElements.each(function (index, el) {
el.style.display = 'block';
});
var contentElements = $(clazz + '.content');
contentElements.each(function (index, el) {
el.style.display = 'none';
});
}
function hideLoading(clazz) {
console.log('hideLoading' + clazz);
var loadingElements = $(clazz + '.loading');
loadingElements.each(function (index, el) {
el.style.display = 'none';
});
var contentElements = $(clazz + '.content');
contentElements.each(function (index, el) {
el.style.display = 'block';
});
}