[OmniFaces utilities] The
createAjaxBehavior()
method creates an ajax behavior which should invoke an ajax listener method expression based on the given EL expression. The target method must take an
AjaxBehaviorEvent
as argument. Note that this is essentially the programmatic equivalent of
<f:ajax>
. So if you intented to create for example a
<p:ajax>
programmatically, then don't use this method. Check also the
UIComponentBase#addClientBehavior(String, ClientBehavior)
whereby the string argument represents the client event name, such as
action
,
valueChange
,
click
,
blur
, etc.
Method:
Usage:
Let's
suppose that we have the following simple form:
<h:form>
...
<h:commandButton value="Save"/>
</h:form>
Further, we
want to programmatically add an AJAX behavior (like <f:ajax/>) to the above button, and for this
we can write a tag handler that exploits the Components#createAjaxBehavior(). Below is
listed only the apply() method (notice the pointed listener, #{commandBean.save}):
@Override
public void
apply(FaceletContext ctx, UIComponent parent) throws IOException {
// avoid the following code to be executed multiple time in the same request
if (!ComponentHandler.isNew(parent)) {
return;
}
// obviously, if the parent is not a ClientBehaviorHolder then is not capable to deal with an AJAX behavior
if (!(parent instanceof ClientBehaviorHolder))
{
return;
}
AjaxBehavior ajaxBehavior =
Components.createAjaxBehavior("#{commandBean.save}");
ClientBehaviorHolder clientBehaviorHolder =
(ClientBehaviorHolder) parent;
clientBehaviorHolder.addClientBehavior("action",
ajaxBehavior);
}
Or, in
order to avoid the risk of adding twice the same AJAX behavior:
AjaxBehavior ajaxBehavior =
Components.createAjaxBehavior("#{commandBean.save}");
ClientBehaviorHolder
clientBehaviorHolder = (ClientBehaviorHolder) parent;
List<ClientBehavior>
behaviors = clientBehaviorHolder.getClientBehaviors().get("action");
// Guard
against adding ourselves twice
if
(behaviors == null || !behaviors.contains(ajaxBehavior)) {
clientBehaviorHolder.addClientBehavior("action",
ajaxBehavior);
}
Further,
the form will become:
<h:form>
<h:outputScript name="jsf.js"
library="javax.faces" target="head"/>
<h:commandButton
value="Save">
<t:simpleAjax/>
</h:commandButton>
</h:form>
Notice that
we have explicitly added the jsf.js resource. By default, when JSF finds
an AJAX behavior in the current view it will "install" this resource
automatically (e.g. in Mojarra, via com.sun.faces.facelets.tag.jsf.core.AjaxHandler#installAjaxResourceIfNecessary()). But,
notice that this is true from AJAX behavior explicitly defined in view, not
programmatically. Depending on context, the jsf.js can be
added via @ResourceDependency (not the case here, but when it is
use: @ResourceDependency(library="javax.faces",
name="jsf.js", target="head")), or via <h:outputScript>). Of
course, you can have a helper method also (maybe inspired from Mojarra source
code).
Finally,
the listener (#{commandBean.save}) is
defined in CommandBean, as:
public void
save(AjaxBehaviorEvent evt) {
LOG.log(Level.INFO, "---------------------Saving----------------------
/ {0}", evt);
}
Note If you
need to go deeper and understand how Components#createAjaxBehavior()is
implemented, then you can check the com.sun.faces.facelets.tag.jsf.core.AjaxHandler
methods,
especially, AjaxHandler#applyAttachedObject()and AjaxHandler#createAjaxBehavior().
The
complete code of this example is on
GitHub.