JSF: How to attach an actionListener to component created programatically?

jsf

Solution

First, you need to manually assign ID to any dynamically created `UINamingContainer`, `UIInput` and `UICommand` components. Otherwise JSF can't locate them in the component tree based on the request parameters, because it wouldn't match the autogenerated ID's.

Thus, at least do:

HtmlCommandLink link = new HtmlCommandLink();
link.setId("linkId");
// ...

Second, you're supposed to create an `ActionListener` as `MethodExpression` as follows:

FacesContext context = FacesContext.getCurrentInstance();
MethodExpression methodExpression = context.getApplication().getExpressionFactory().createMethodExpression(
    context.getELContext(), "#{bean.actionListener}", null, new Class[] { ActionEvent.class });

link.addActionListener(new MethodExpressionActionListener(methodExpression));
// ...

...and of course have the following method in the backing bean class behind `#{bean}`:

public void actionListener(ActionEvent event) {
    // ...
}

All the above dynamic stuff basically does the same as the following raw JSF tag:

<h:commandLink id="linkId" actionListener="#{bean.actionListener}" />

Problem

I have to create some commandLinks dynamically and attach some action listener to it, So I've put `<h:panelGrid>` on the JSP page and used such code to add the commandLinks and to assign action listeners to: ``` public ManagedBean(){ List<UIComponenet> child = panelGrid.getChilderen(); list.clear(); List<MyClass> myList = getSomeList(); for (MyClass myObj : myList){ FacesContext ctx = FacesContext.getCurrentContext(); HtmlCommandLink cmdLink = (HtmlCommandLink) ctx.getApplication.createComponent(HtmlCommandLink.COMPONENT_TYPE); cmdLink.setValue(myObj.getName()); cmdLink.setActionLinstner(new ActionListener(){ public void processAction(ActionEvent event) throws AbortProcessingException{ System.out.println (">>>>>>>>>>>>>>>>>I am HERE "); } }); child.add(cmdLink); } } ``` But unfortunately, when I press this commandLinks, an exception thrown! How can I add component event listeners at runtime? (Note, the code above my contain syntax/compilation errors as I just wrote).

Original source