This recipe will continue with the discussion on RequestContext
that we began in the previous recipes. There may be cases where we need values from backing beans in AJAX callbacks. Let's suppose we have a form in a dialog; when the user submits the form, the dialog should stay open to display any validation errors and it should be closed otherwise.
In this recipe, we will learn how the described task can be done with AJAX callback parameters. We will develop an oncomplete
callback for a command button within p:dialog
.
The developed page contains a Dialog
component with an input field. The dialog will be visible when the page is loaded. There is only one valid input value, PrimeFaces Cookbook
. When the user inputs this value and clicks on the Save button, the dialog should be closed. In any other case, it should stay open. The p:commandButton
button defines handleComplete(xhr, status, args)
, an oncomplete
callback. It gets processed when the AJAX request completes. There, we check args.validName
and close the dialog if this value is true
. Here's the code for this discussion:
<p:growl id="growl" autoUpdate="true"/> <p:dialog header="What is the name of this book?" visible="true" widgetVar="dlgWidget"> <p:inputText id="name" value="#{ajaxCallbackParamBean.name}"/> <p:commandButton id="save" value="Save" style="margin:10px;" process="@this name" update="name" actionListener="#{ajaxCallbackParamBean.save}" oncomplete="handleComplete(xhr, status, args)"/> </p:dialog> <h:outputScript id="handleCompleteScript" target="body"> function handleComplete(xhr, status, args) { if (args && args.validName) { PF('dlgWidget').hide(); } } </h:outputScript>
The corresponding CDI bean compares the input value with the valid one and creates either an information message or an error message for the growl
component. Furthermore, it adds a callback parameter, validName
, with the value true
for a valid input and false
otherwise. Here's the code that encapsulates this discussion:
@Named @ViewScoped public class AjaxCallbackParamBean implements Serializable { private String name; public void save(ActionEvent ae) { RequestContext requestContext = RequestContext.getCurrentInstance(); String message; FacesMessage.Severity severity; UIInput input = (UIInput) ae.getComponent(). findComponent("name"); if ("PrimeFaces Cookbook".equals(name)) { message = "All right!"; severity = FacesMessage.SEVERITY_INFO; requestContext.addCallbackParam("validName", true); input.setValid(true); } else { message = "Name is wrong, try again"; severity = FacesMessage.SEVERITY_ERROR; requestContext.addCallbackParam("validName", false); input.setValid(false); } FacesMessage msg = new FacesMessage(severity, message, null); FacesContext.getCurrentInstance().addMessage(null, msg); } // getters / setters ... }
The following screenshot shows the dialog and the growl notification that is created when there is an error:
The oncomplete
callback function takes three arguments: XMLHttpRequest
, status string, and optional parameters provided by the RequestContext
API. Parameters can be added by the addCallbackParam(key, value)
method. They are serialized to JavaScript Object Notation (JSON) and can be accessed in AJAX callbacks by the args
argument. In the example, we accessed the value of the validName
callback parameter by args.validName
. We can add as many callback parameters as we want. Primitive values are supported as well as Plain Old Java Objects (POJOs). POJOs are serialized to JSON as well.
In the bean, we set the valid
flag on the input component to false
when the book's name is wrong. Making the input component invalid leads to red borders around the input field in the UI.
If we had the standard h:inputText
component instead of the PrimeFaces' one, the input.setValid(false)
setting on the input component would not lead to red borders around the input field in the UI. In this case, we could highlight the invalid input field anyway by adding the ui-state-error
style class via JavaScript. Here's the code we are discussing:
function handleComplete(xhr, status, args) { if (args && args.validName) { PF('dlgWidget').hide(); } else { $('#name').addClass('ui-state-error'), } }
This recipe is available in the demo web application on GitHub (https://github.com/ova2/primefaces-cookbook/tree/second-edition). Clone the project if you have not done it yet, explore the project structure, and build and deploy the WAR file on application servers compatible with Servlet 3.x, such as JBoss WildFly and Apache TomEE.
The showcase for the recipe is available at http://localhost:8080/pf-cookbook/views/chapter11/ajaxCallbacks.jsf
.
3.144.119.170