Pass a method expression to a custom component

1.2k views Asked by At

I'm looking for a minimal example on how to pass a method expression to a custom component. I tried the following, but the responsible setter of my component is never called.

Bean for my view:

public String bar(){
    //do stuff
    return "";
}


My view:

<my:comp foo="#{bean.bar}" />


Bean for my component:

private static final String FOO = "foo";
public void setFoo(MethodExpression me){
    //never called
    getStateHelper().put(FOO, me);
}

public MethodExpression getFoo(){
    //actually gets called
    return (MethodExpression) getStateHelper().get(FOO);
}


Inside my component renderer, I call component.getFoo() and get a NPE.

1

There are 1 answers

2
BalusC On

You need to implement the ActionSource2 interface:

@FacesComponent(MyComponent.COMPONENT_TYPE)
public class Mycomponent extends UIComponentBase implements ActionSource2 {
    // ...
}

Or, easier, to extend from UICommand class (which are also used by <h:commandXxx> components) which has all of those ActionSource2 methods already implemented the right way so that you don't need to repeat the job:

@FacesComponent(MyComponent.COMPONENT_TYPE)
public class Mycomponent extends UICommand {
    // ...
}

Either way, you can use action="#{some method expression}" and even attach actionlisteners on it. Note that you can't rename the attribute name action. It really has to be action.

An open source example of such a custom component is the OmniFaces <o:commandScript>. The source code is available here.