Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically add an AjaxBehavior to a UIComponent with primefaces

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]);
            }
        }
    }

}
like image 483
Bardelman Avatar asked Apr 04 '13 10:04

Bardelman


1 Answers

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");
}
like image 188
Yougesh Avatar answered Nov 15 '22 04:11

Yougesh