BlockUI blocks any piece(s) of a page, or the entire page, during Ajax calls. A "source" component blocks one or more "target" components with an overlay and custom content.
Uses the widget's block() / unblock() as onstart / oncomplete callbacks. Add a message, or page and sort the table.
With autoShow="true" the source component's Ajax events (see event) block the target component(s) automatically.
Only events defined by p:ajax are supported. Expand, select or unselect a tree node, or click a checkbox.
The entire page is blocked when the target attribute is omitted. The button blocks the whole page for the duration of the Ajax call.
A non-centered message defined by css and centerX / centerY, a styled overlay via cssOverlay,
and auto-unblocking after timeout milliseconds. The whole page is blocked for two seconds.
There are two ways to use BlockUI. The first uses the widget's JavaScript API (block() / unblock()) in onstart / oncomplete callbacks.
The second, so-called autoShow mode, hooks into jQuery global Ajax callbacks so no explicit calls are needed.
Components and p:ajax with global="false" do not trigger BlockUI in autoShow mode.
Some HTML elements such as table or span cannot be blocked; wrap them in a div (h:panelGroup layout="block").
Multiple blockings of the same element by different Ajax calls are tracked: the element is unblocked only after all calls have finished.
<style>
#formBlockUIAjax\:blockUIContent td {
border: none !important;
padding: 0 !important;
}
</style>
<div class="card">
<h5>Basic usage with p:ajax</h5>
<p>Uses the widget's <code>block()</code> / <code>unblock()</code> as <code>onstart</code> / <code>oncomplete</code> callbacks. Add a message, or page and sort the table.</p>
<h:form id="formBlockUIAjax">
<p:messages id="messages"/>
<div class="grid">
<div class="col-12 md:col-4">
<h:panelGroup id="messageDetailGroup" layout="block">
<h:panelGrid id="messageDetail" columns="1">
<h:outputText value="Subject *"/>
<h:inputText value="#{dataTableController.newSubject}" required="true" label="Subject"/>
<h:outputText value="Text *"/>
<h:inputText value="#{dataTableController.newText}" required="true" label="Text"/>
</h:panelGrid>
<p:commandButton id="addMsgButton" value="Add message" action="#{dataTableController.addMessage}"
process="messageDetailGroup" update="messageDetail dataTable messages"
style="margin-top: 20px;" icon="pi pi-plus"
onstart="PF('blockUIWidget1').block()" oncomplete="PF('blockUIWidget1').unblock()"/>
</h:panelGroup>
</div>
<div class="col-12 md:col-8">
<p:dataTable id="dataTable" var="message" value="#{dataTableController.messages}" paginator="true"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rows="5" rowsPerPageTemplate="5,10,15" paginatorPosition="bottom">
<p:ajax event="page" listener="#{dataTableController.doSomething}" update="messages"
onstart="PF('blockUIWidget2').block()" oncomplete="PF('blockUIWidget2').unblock()"/>
<p:ajax event="sort" listener="#{dataTableController.doSomething}" update="messages"
onstart="PF('blockUIWidget2').block()" oncomplete="PF('blockUIWidget2').unblock()"/>
<p:column sortBy="#{message.subject}" headerText="Subject">
<h:outputText value="#{message.subject}"/>
</p:column>
<p:column sortBy="#{message.text}" headerText="Text">
<h:outputText value="#{message.text}"/>
</p:column>
</p:dataTable>
</div>
</div>
<pe:blockUI target="messageDetailGroup" widgetVar="blockUIWidget1">
<h:panelGrid columns="2">
<h:graphicImage library="images" name="ajax-loader1.gif"
style="margin-right: 12px; vertical-align: middle;"/>
<h:outputText value="Adding message..." style="white-space: nowrap;"/>
</h:panelGrid>
</pe:blockUI>
<pe:blockUI target="dataTable" content="blockUIContent" widgetVar="blockUIWidget2"/>
<h:panelGrid id="blockUIContent" columns="2" style="display:none;table-layout:auto;">
<h:graphicImage library="images" name="ajax-loader1.gif"
style="margin-right: 12px; vertical-align: middle;"/>
<h:outputText value="Please wait, data is being processed..." style="white-space: nowrap;"/>
</h:panelGrid>
</h:form>
</div>
<div class="card">
<h5>AutoShow mode and more</h5>
<p>With <code>autoShow="true"</code> the <code>source</code> component's Ajax events (see <code>event</code>) block the <code>target</code> component(s) automatically.
Only events defined by <code>p:ajax</code> are supported. Expand, select or unselect a tree node, or click a checkbox.</p>
<h:form id="formBlockUIAutoShow">
<h:panelGroup id="viewArea" layout="block">
<div class="grid">
<div class="col-12 md:col-6">
<h:panelGroup layout="block" styleClass="blockable">
<p:tree id="fileSystem" value="#{fileSystemController.root}" var="node" dynamic="true"
cache="false" selectionMode="single" selection="#{fileSystemController.selectedNode}">
<p:ajax event="expand" update="accessRightsGroup"
listener="#{fileSystemController.onNodeExpand}"/>
<p:ajax event="select" update="accessRightsGroup"
listener="#{fileSystemController.onNodeSelect}"/>
<p:ajax event="unselect" update="accessRightsGroup"
listener="#{fileSystemController.onNodeUnselect}"/>
<p:treeNode>
<h:outputText value="#{node}"/>
</p:treeNode>
</p:tree>
</h:panelGroup>
</div>
<div class="col-12 md:col-6">
<h:panelGroup layout="block" id="accessRightsGroup" styleClass="blockable">
<h:outputText value="Access rights for #{fileSystemController.selectedNode.data}"
rendered="#{not empty fileSystemController.selectedNode}"/>
<h:outputText value="No tree node is selected" rendered="#{empty fileSystemController.selectedNode}"/>
<h:selectManyCheckbox id="accessRights" value="#{accessRightsController.selectedAccessRights}"
styleClass="checkBoxes" layout="pageDirection" style="margin-top: 10px;">
<f:selectItems value="#{accessRightsController.accessRights}"/>
<p:ajax process="@this"/>
</h:selectManyCheckbox>
<pe:blockUI source="accessRights" target="@(.blockable)" autoShow="true">
<h:panelGrid columns="2">
<h:graphicImage library="images" name="ajax-loader1.gif"
style="margin-right: 12px; vertical-align: middle;"/>
<h:outputText value="Checkbox clicked..." style="white-space: nowrap;"/>
</h:panelGrid>
</pe:blockUI>
</h:panelGroup>
</div>
</div>
</h:panelGroup>
<pe:blockUI source="fileSystem" target="viewArea" event="expand,select,unselect" autoShow="true">
<h:panelGrid columns="2">
<h:graphicImage library="images" name="ajax-loader1.gif"
style="margin-right: 12px; vertical-align: middle;"/>
<h:outputText value="Tree event is running..." style="white-space: nowrap;"/>
</h:panelGrid>
</pe:blockUI>
</h:form>
</div>
<div class="card">
<h5>Page Blocking</h5>
<p>The entire page is blocked when the <code>target</code> attribute is omitted. The button blocks the whole page for the duration of the Ajax call.</p>
<h:form id="formBlockPage">
<p:commandButton value="Block this page!" action="#{blockUIController.doSomething}" update="@none"
onstart="PF('blockUIWidgetPage').block()" oncomplete="PF('blockUIWidgetPage').unblock()"/>
<pe:blockUI widgetVar="blockUIWidgetPage" cssOverlay="{opacity:0.5}">
<h:panelGrid columns="2">
<h:graphicImage library="images" name="ajax-loader1.gif"
style="margin-right: 12px; vertical-align: middle;"/>
<h:outputText value="Please wait..." style="white-space: nowrap;"/>
</h:panelGrid>
</pe:blockUI>
</h:form>
</div>
<div class="card">
<h5>Non-centered message, auto-unblock and more</h5>
<p>A non-centered message defined by <code>css</code> and <code>centerX</code> / <code>centerY</code>, a styled overlay via <code>cssOverlay</code>,
and auto-unblocking after <code>timeout</code> milliseconds. The whole page is blocked for two seconds.</p>
<h:form id="formBlockCustom">
<p:commandButton value="Block this page!" type="button"
onclick="PF('blockUIWidgetCustom').block()"/>
<pe:blockUI widgetVar="blockUIWidgetCustom"
css="{top: '10px', left: '', right: '10px', cursor: 'wait'}"
cssOverlay="{backgroundColor: 'red'}"
timeout="2000"
centerY="false">
<h:panelGrid columns="2">
<h:graphicImage library="images" name="ajax-loader1.gif"
style="margin-right: 12px; vertical-align: middle;"/>
<h:outputText value="This is a non-centered message. Please wait..." style="white-space: nowrap;"/>
</h:panelGrid>
</pe:blockUI>
</h:form>
</div>
package org.primefaces.extensions.showcase.controller;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
/**
* DataTableController
*
* @author Thomas Andraschko / last modified by $Author$
* @version $Revision$
*/
@Named
@ViewScoped
public class DataTableController implements Serializable {
@Serial
private static final long serialVersionUID = 20111020L;
private List<Message> messages;
private List<Message> filteredMessages;
private String newSubject = "my subject";
private String newText = "my text";
public DataTableController() {
if (messages == null) {
messages = new ArrayList<>();
for (int i = 0; i < 100; i++) {
final Message message = new Message();
message.setSubject("subject " + i);
message.setText("text " + i);
messages.add(message);
}
}
}
public List<Message> getMessages() {
return messages;
}
public void setMessages(final List<Message> messages) {
this.messages = messages;
}
public List<Message> getFilteredMessages() {
return filteredMessages;
}
public void setFilteredMessages(final List<Message> filteredMessages) {
this.filteredMessages = filteredMessages;
}
public String getNewSubject() {
return newSubject;
}
public void setNewSubject(final String newSubject) {
this.newSubject = newSubject;
}
public String getNewText() {
return newText;
}
public void setNewText(final String newText) {
this.newText = newText;
}
public String addMessage() {
doSomething();
final Message message = new Message();
message.setSubject(newSubject);
message.setText(newText);
messages.add(0, message);
newSubject = "";
newText = "";
final FacesContext fc = FacesContext.getCurrentInstance();
fc.addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "New message has been added successfully", null));
return null;
}
public void doSomething() {
try {
// simulate a long running request
Thread.sleep(1500);
}
catch (final Exception e) {
// Restore interrupted state...
Thread.currentThread().interrupt();
}
}
public class Message implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String subject;
private String text;
private long time;
public Message() {
time = System.currentTimeMillis() + (long) (ThreadLocalRandom.current().nextDouble() * 10);
}
public final String getSubject() {
return subject;
}
public final void setSubject(final String subject) {
this.subject = subject;
}
public final String getText() {
return text;
}
public final void setText(final String text) {
this.text = text;
}
public long getTime() {
return time;
}
public void setTime(final long time) {
this.time = time;
}
}
}
package org.primefaces.extensions.showcase.controller.blockui;
import java.io.*;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.NodeUnselectEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
/**
* TreeBean
*
* @author Oleg Varaksin / last modified by $Author$
* @version $Revision$
*/
@Named
@ViewScoped
public class FileSystemController implements Serializable {
@Serial
private static final long serialVersionUID = 20111229L;
private final TreeNode root;
private TreeNode selectedNode;
public FileSystemController() {
root = new DefaultTreeNode("Root", null);
final TreeNode node0 = new DefaultTreeNode("Folder 0", root);
final TreeNode node1 = new DefaultTreeNode("Folder 1", root);
final TreeNode node2 = new DefaultTreeNode("Folder 2", root);
final TreeNode node00 = new DefaultTreeNode("Folder 0.0", node0);
final TreeNode node01 = new DefaultTreeNode("Folder 0.1", node0);
final TreeNode node10 = new DefaultTreeNode("Folder 1.0", node1);
new DefaultTreeNode("File 1.1", node1);
new DefaultTreeNode("File 2.0", node2);
new DefaultTreeNode("File 0.0.0", node00);
new DefaultTreeNode("File 0.0.1", node00);
new DefaultTreeNode("File 0.1.0", node01);
new DefaultTreeNode("File 1.0.0", node10);
}
public TreeNode getRoot() {
return root;
}
public TreeNode getSelectedNode() {
return selectedNode;
}
public void setSelectedNode(final TreeNode selectedNode) {
this.selectedNode = selectedNode;
}
public void onNodeExpand(final NodeExpandEvent event) {
doSomething();
}
public void onNodeSelect(final NodeSelectEvent event) {
selectedNode = event.getTreeNode();
doSomething();
}
public void onNodeUnselect(final NodeUnselectEvent event) {
selectedNode = null;
doSomething();
}
public void doSomething() {
try {
// simulate a long running request
Thread.sleep(1200);
}
catch (final Exception e) {
// Restore interrupted state...
Thread.currentThread().interrupt();
}
}
}
package org.primefaces.extensions.showcase.controller.blockui;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import jakarta.faces.model.SelectItem;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
/**
* AccessRightsController
*
* @author Oleg Varaksin / last modified by $Author$
* @version $Revision$
*/
@Named
@ViewScoped
public class AccessRightsController implements Serializable {
@Serial
private static final long serialVersionUID = 20111229L;
private List<SelectItem> accessRights = new ArrayList<>();
private List<SelectItem> selectedAccessRights = new ArrayList<>();
public AccessRightsController() {
accessRights.add(new SelectItem("View", "View"));
accessRights.add(new SelectItem("Read", "Read"));
accessRights.add(new SelectItem("Write", "Write"));
accessRights.add(new SelectItem("Execute", "Execute"));
accessRights.add(new SelectItem("Delete", "Delete"));
accessRights.add(new SelectItem("Full", "Full"));
}
public List<SelectItem> getAccessRights() {
return accessRights;
}
public void setAccessRights(List<SelectItem> accessRights) {
this.accessRights = accessRights;
}
public List<SelectItem> getSelectedAccessRights() {
try {
// simulate a long running request
Thread.sleep(1200);
}
catch (Exception e) {
// Restore interrupted state...
Thread.currentThread().interrupt();
}
return selectedAccessRights;
}
public void setSelectedAccessRights(List<SelectItem> selectedAccessRights) {
this.selectedAccessRights = selectedAccessRights;
}
}
package org.primefaces.extensions.showcase.controller.blockui;
import java.io.*;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
/**
* BlockUIController
*
* @author Oleg Varaksin / last modified by $Author$
* @version $Revision$
*/
@Named
@ViewScoped
public class BlockUIController implements Serializable {
@Serial
private static final long serialVersionUID = 20130903L;
public void doSomething() {
try {
// simulate a long running request
Thread.sleep(1200);
}
catch (final Exception e) {
// Restore interrupted state...
Thread.currentThread().interrupt();
}
}
}