0

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
FeinesFabi
  • 1,147
  • 2
  • 12
  • 25

1 Answers1

2

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks for the advice. I've read up some facts about the topic and learned, that a `ComponentHandler` is required, which takes care of the `action` param. See [link](http://jdevelopment.nl/passing-action-methods-facelets-tags/). But I think I'll try to avoid the whole issue by using some kind of onClick handler with jQuery. – FeinesFabi Sep 05 '13 at 12:50
  • The handler is not required. It's already taken care of by JSF if you implement the right interface or extend from the right component. Have you in any way seen the source code of the command script example? A single component class is *all* you need (apart from an obvious entry in taglib.xml of course). So I have absolutely no idea what exactly you mean with "whole issue". Isn't the "issue" just ignorance? – BalusC Sep 05 '13 at 13:14