0

I have a bean class that represents a calculator. This class exposes 4 methods: add, subtract, multiply, and divide.

For the front end I am writing a JSP page. This page contains two text input boxes (one for x, and one for y). I have a pulldown menu where the user selects the operation and then one Calculate command button that performs the selected operation.

<h:form>
    <h:inputText value="#{calcBean.x}"></h:inputText>
    <h:inputText value="#{calcBean.y}"></h:inputText>
    <h:selectOneMenu>
        <f:selectItem itemValue="Add"></f:selectItem>
        <f:selectItem itemValue="Subtract"></f:selectItem>
        <f:selectItem itemValue="Multiply"></f:selectItem>
        <f:selectItem itemValue="Divide"></f:selectItem>
    </h:selectOneMenu>
    <h:commandButton value="Calculate" action="@SEE COMMENT">
    <%-- TODO the action of this command button needs to change depending on --%>
    <%-- the user selection. For example: If the user selects "Add" the action --%>
    <%-- needs to be #{calcBean.add} --%>
    </h:commandButton>
</h:form>

The issue I am running into is I don't know how to change the action of the command button depending on the user selection.

I could do this with four different command buttons but that is not an elegant solution:

<h:form>
    <h:inputText value="#{calcBean.x}"></h:inputText>
    <h:inputText value="#{calcBean.y}"></h:inputText>
    <br/>
    <h:commandButton value="Add" action="#{calcBean.add}"></h:commandButton>
    <h:commandButton value="Subtract" action="#{calcBean.subtract}"></h:commandButton>
    <h:commandButton value="Multiply" action="#{calcBean.multiply}"></h:commandButton>
    <h:commandButton value="Divide" action="#{calcBean.divide}"></h:commandButton>
</h:form>
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
Jan Tacci
  • 3,131
  • 16
  • 63
  • 83

2 Answers2

1

You can do this by binding the user's selection to a property in the backing bean and using that selected value as a condition in your action method to do the proper calculation.

<h:selectOneMenu value=#{calcBean.calculationType}>
    <f:selectItem itemValue="Add"></f:selectItem>
    <f:selectItem itemValue="Subtract"></f:selectItem>
    <f:selectItem itemValue="Multiply"></f:selectItem>
    <f:selectItem itemValue="Divide"></f:selectItem>
</h:selectOneMenu>

<h:commandButton value="Add" action="#{calcBean.doSelectedCalculation}"></h:commandButton>

In your single unique action method, according to the selected calculation type you can do operation on the given x and y values.

public void doSelectedCalculation()
{
     if(calculationType.equals("Add"))
     {
          result = x + y;
     }
     else if(calculationType.equals("Subtract"))
     { 
          result = x - y;
     }
     ...

}
cubbuk
  • 7,800
  • 4
  • 35
  • 62
  • This is a rather different way of thinking about things. It's almost as if you have to code the bean with an understanding that it will be accessed via a JSF frontend. It would be nice if the two were not tightly coupled. – Jan Tacci Jan 21 '13 at 22:46
  • 1
    @JanTacci yes, the managed bean is written thinking how the View (JSP or Facelets page) will consume it, but this is in order that one or many views can use a single managed bean i.e. an application scoped managed bean that provides a list to fill a `Select your theme` option list enabled in all pages. – Luiggi Mendoza Jan 21 '13 at 23:08
  • You are welcome, and plus 1 to Luigi Mendoza's comments, designing your beans and pages in this way will make things much easier for you when you got accustomed to it =) – cubbuk Jan 22 '13 at 06:14
1

The JSF-ish way would be:

  1. Bind your <h:selectOneMenu> with a property in your managed bean, let's say, int selectedOption.

  2. Set values for the options (<f:selectItem>) showed to the user. It could be 1, 2, 3 and 4 (just for a basic example)

  3. Have a single method calculate exposed from your managed bean. This method will be in your <h:commandButton> action attribute. This method will use the selectedOption attribute to know what the operation to use.

With this info, the result would be:

JSF code

<h:form>
    <h:inputText value="#{calcBean.x}" />
    <h:inputText value="#{calcBean.y}" />
    <h:selectOneMenu value="#{calcBean.selectedOption}">
        <f:selectItem itemLabel="Add" itemValue="1" />
        <f:selectItem itemLabel="Subtract" itemValue="2" />
        <f:selectItem itemLabel="Multiply" itemValue="3" />
        <f:selectItem itemLabel="Divide" itemValue="4" />
    </h:selectOneMenu>
    <h:commandButton value="Calculate" action="#{calcBean.calculate}" />
</h:form>
Result: <h:outputText value="#{calcBean.result}" />

CalcBean code

public class CalcBean {

    private int x;
    private int y;
    private int selectedOption;
    private double result;
    //constructor...
    //getters and setters...

    public String calculate() {
        result = 0;
        switch(selectedOption) {
            case 1:
                result = x + y;
                break;
            //write the other cases...
        }
        return null;
    }
}

The code above correspond to JSF 1.2. If you're using JSF 2.x, then you should stop using JSP and move to Facelets, as explained in the JSF wiki. IMHO it would be better to learn JSF 2 instead of JSF 1.x.

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Great! Thank you. @See my comment above. It's a whole new way of thinking about programming if you know that a JSF page will be accessing your code. If you had already coded up a calculator class without knowledge of the user interface would you have to code something like a "Bean proxy" that uses your "normal" calculator class in a JSF sort of way? – Jan Tacci Jan 21 '13 at 22:47
  • I am new to all this... my intention was to learn JSF.. are you saying that what I am doing isn't even JSF? It's JSP? – Jan Tacci Jan 21 '13 at 22:52
  • What I'm saying is that JSF 1.x was built thinking in JSP, but from JSF 2 you can (and it would be better to) use Facelets. It's all explained in the link at the bottom of my answer, please click on it and read, there's lot of info to process and learn, but it will be for good. Also, you started with a basic exercise of JSF, I just tried to help you to finish it. There can be other ways to do it using JSF. – Luiggi Mendoza Jan 21 '13 at 23:03
  • @JanTacci Also, why I said *The JSF-ish way* in my answer? Because you could have done other tricks using JavaScript and multiple `` hidden to the user **or** passing raw parameters to the server and processing them in your managed bean. But JSF simplifies all this for you and provides an easy way to solve it. – Luiggi Mendoza Jan 21 '13 at 23:05