How to invoke a bean action method using a link? The onclick does not work

actionmethod, hyperlink, jsf, jsf-2, onclick

Solution

In order to invoke a bean action method on click of a link, you need `<h:commandLink>`. This must be enclosed in a `<h:form>`.

<h:form>
    <h:commandLink ... action="#{bean.action}" />
</h:form>
public String action() {
    // ...

    return "/other.xhtml";
}

In JSF, only the attributes which interpret the EL expression as a `MethodExpression` can be used to declare action methods. All other attributes are interpreted as `ValueExpression` and they are immediately executed when the HTML output is generated by JSF. This covers the `onclick` attribute, whose value should actually represent a JavaScript function.

In case you actually want to use a GET link, then move the action method to a `<f:viewAction>` in the target page. This will be invoked on page load of the target page.

<h:link ... outcome="/other.xhtml" />
<f:metadata>
    <f:viewAction action="#{bean.onload}" />
</f:metadata>
public void onload() {
    // ...
}

See also:

- When should I use h:outputLink instead of h:commandLink?

- How to send form input values and invoke a method in JSF bean

- How do I process GET query string URL parameters in backing bean on page load?

- How to navigate in JSF? How to make URL reflect current page (and not previous one)

Following your advices I placed all the links in a form

The communication between the command Link and the managed bean is working but in the UI only the last commandLink (close action) is displayed.

You should not bind multiple physically different components to one and same bean property. Also the `<f:attribute>` to pass arguments is hacky and not necessary anymore in JSF2. Assuming that you're using a Servlet 3.0 / EL 2.2 container (your question history confirms that you're using Glassfish 3), rather just pass the argument as method argument directly:

<h:commandLink id="Link1" value="Up" action="#{accountController.moveUserUp(user)}" />
<h:commandLink id="Link2" value="Down" action="#{accountController.moveUserDown(user)}" />
<h:commandLink id="Link3" value="Delete" action="#{accountController.deleteUser(user)}" />

with

public void moveUserUp(User user) {
    // ...
}

public void moveUserDown(User user) {
    // ...
}

public void deleteUser(User user) {
    // ...
}

See also:

- How does the 'binding' attribute work in JSF? When and how should it be used?

- Invoke direct methods or methods with arguments / variables / parameters in EL

Problem

I'm trying to implement a list of users names which can be rearranged by clicking on UP or DOWN links. ``` <ul> <ui:repeat var="user" value="#{cc.attrs.value}"> <li> #{user.name} <h:link outcome = "user" value = "left" onclick="#{accountController.moveDown}"> <f:param name="id" value = "${user.id}" /> </h:link> </li> </ui:repeat> </ul> ``` The problem here is that it seems that I'm not using the onclick attribute correctly. What is the proper way for doing this? Edit: Following your advices I placed all the links in a form: ``` <h:form> <ui:repeat value="#{cc.attrs.value}" var = "user"> <div class = "user"> <h:commandLink id = "Link1" value = "Up" binding = "#{accountController.ommandLink}" action = "#{accountController.moveUserUp}"> <f:attribute name = "userId" value = "#{user.id}" /> </h:commandLink> <h:commandLink id = "Link2" value = "Down" binding = "#{accountController.commandLink}" action = "#{accountController.moveUserDown}"> <f:attribute name = "userId" value = "#{user.id}" /> </h:commandLink> <h:commandLink id = "Link3" value = "Delete" binding = "#{accountController.commandLink}" action = "#{accountController.deleteUser}"> <f:attribute name = "userId" value = "#{user.id}" /> </h:commandLink> </div> </h:form> ``` the Managed Bean: ``` private UIComponent commandLink; public void moveUserUp(){ Integer userId = (Integer)commandLink.getAttributes().get("userId"); System.out.println("MOVE TAB LEFT :" + userId); } public void moveUserDown(){ Integer userId = (Integer)commandLink.getAttributes().get("userId"); System.out.println("MOVE TAB RIGHT: " + userId); } public void deleteUser(){ Integer userId = (Integer)commandLink.getAttributes().get("userId"); System.out.println("DELETE TAB: " + userId); } public UIComponent getCommandLink() { return commandLink; } public void setCommandLink(UIComponent commandLink) { this.commandLink = commandLink; } ``` The communication between the command Link and the managed bean is working but in the UI only the last commandLink (close action) is displayed.

Original source

Related problems