How to programmatically add an AjaxBehavior to a UIComponent with primefaces
ajax, jsf-2, primefaces
Solution
Do something like this
Panel tp = new Panel();
FacesContext fc = FacesContext.getCurrentInstance();
ExpressionFactory ef = fc.getApplication().getExpressionFactory();
MethodExpression me = ef.createMethodExpression(fc.getELContext(), "#{myView.closeIt}", null, new Class<?>[]{BehaviorEvent.class});
AjaxBehavior ajaxBehavior = (AjaxBehavior) fc.getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);
ajaxBehavior.setProcess("@this");
ajaxBehavior.addAjaxBehaviorListener(new AjaxBehaviorListenerImpl(me, me));
tp.addClientBehavior("close", ajaxBehavior);
component.getChildren().add(tp);
myView.closeIt()
public void closeIt(CloseEvent ce){
Panel p = (Panel) ce.getComponent();
System.out.println("Do what ever you want");
}
Problem
Since i've asked my last question (which still unanswered) i continued searching for a solution and lastly i found this topic which i think can help achieve what i want. So , i tried that solution (which itself is a workaround) but it still didn't work for me. Here is the code, it s all just a test for this issue : the index.xhtml : ``` <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:c="http://java.sun.com/jsp/jstl/core"> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> <title>dyn add comps test </title> </h:head> <body> <h:form id="form1"> <!-- once this first commandLink is clisked it will generate another commandlink below it --> <h:commandLink value="cliick me"> <f:ajax event="click" listener="#{myBean.firstcmdLinkListenerHandler}"/> </h:commandLink> </h:form> </body> </html> ``` The managed Bean : MyBean.java ``` package mybeans; import javax.el.ExpressionFactory; import javax.el.MethodExpression; import javax.faces.application.Application; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import javax.faces.component.UIComponent; import javax.faces.component.html.HtmlCommandLink; import javax.faces.context.FacesContext; import javax.faces.event.AjaxBehaviorEvent; import javax.faces.event.BehaviorEvent; import org.primefaces.component.behavior.ajax.AjaxBehaviorListenerImpl; import org.primefaces.context.RequestContext; @ManagedBean @SessionScoped public class MyBean { public void handleClose(AjaxBehaviorEvent abe){ System.out.println("!!!-->>>>> the Ajax Behaviour Works !!!!! "); } public void reLoadCityList( BehaviorEvent event ){ System.out.println("!!!-->>>>> the reLoadCityList method Works !!!!! "); } public void firstcmdLinkListenerHandler(AjaxBehaviorEvent abe){ System.out.println("firstcmdLinkListenerHandleris running ! "); FacesContext fc = FacesContext.getCurrentInstance(); Application application = fc.getApplication(); ExpressionFactory ef = fc.getApplication().getExpressionFactory(); UIComponent form1 = fc.getViewRoot().findComponent("form1"); if(form1!=null){ //Creating the commandLink HtmlCommandLink mynewcmdlink = (HtmlCommandLink)application.createComponent(HtmlCommandLink.COMPONENT_TYPE); mynewcmdlink.setId("mynewcmdlink"); mynewcmdlink.setValue("clickme2!!"); MyAjaxBehavior pajax = new MyAjaxBehavior(); Class[] par = new Class[1]; par[0] = BehaviorEvent.class; //par[0] = AjaxBehaviorEvent.class; (*) //pajax.setListener( myCreateMetExpression( "reLoadCityList", true, //void.class, par ) ); //i tried with both AjaxBehaviorEvent and BehaviorEvent as in (*) //MethodExpression me = ef.createMethodExpression( //fc.getELContext(), "#{myBean.handleClose}", void.class, par); MethodExpression me = ef.createMethodExpression( fc.getELContext(), "#{myBean.reLoadCityList}", void.class, par); //pajax.setListener(me); //i've tried with this too but it wasn't sucesseful pajax.addAjaxBehaviorListener( new AjaxBehaviorListenerImpl( me ) ); pajax.setProcess( "@this" ); mynewcmdlink.addClientBehavior( "change", pajax ); //adding thecommanLink to the form form1.getChildren().add(mynewcmdlink); //Refreshing the form to see the added commandLink : RequestContext context = RequestContext.getCurrentInstance(); context.update("form1"); context.update("form1:foo"); }else System.out.println("form1 is null!!"); } ``` and the MyAjaxBehavior.java used as the workaround in the primefaces forum article: ``` package mybeans; import java.util.HashMap; import javax.el.ELContext; import javax.el.MethodExpression; import javax.faces.component.UIComponentBase; import javax.faces.context.FacesContext; import javax.faces.event.AbortProcessingException; import javax.faces.event.BehaviorEvent; import org.primefaces.component.behavior.ajax.AjaxBehavior; public class MyAjaxBehavior extends AjaxBehavior { @Override public Object saveState(FacesContext context) { HashMap<String, Object> map; map = new HashMap<String, Object>(); map.put("update", getUpdate()); map.put("process", getProcess()); map.put("oncomplete", getOncomplete()); map.put("onerror", getOnerror()); map.put("onsuccess", getOnsuccess()); map.put("onstart", getOnstart()); map.put("listener", getListener()); if (initialStateMarked()) return null; return UIComponentBase.saveAttachedState(context, map); } @SuppressWarnings("unchecked") @Override public void restoreState(FacesContext context, Object state) { if (state != null) { HashMap<String, Object> map; map = (HashMap<String, Object>) UIComponentBase .restoreAttachedState(context, state); setUpdate((String) map.get("update")); setProcess((String) map.get("process")); setOncomplete((String) map.get("oncomplete")); setOnerror((String) map.get("onerror")); setOnsuccess((String) map.get("onsuccess")); setOnstart((String) map.get("onstart")); setListener((MethodExpression) map.get("listener")); } } @Override public void broadcast(BehaviorEvent event) throws AbortProcessingException { ELContext eLContext = FacesContext.getCurrentInstance().getELContext(); // Backward compatible implementation of listener invocation if (getListener() != null) { try { getListener().invoke(eLContext, new Object[] { event }); } catch (IllegalArgumentException exception) { getListener().invoke(eLContext, new Object[0]); } } } } ```