3

So I have bean named element that has a list of categories in and I want to add to that list from a drop down box.

There is a submit at the bottom of the page that persists my element and all works fine, I have a converter in place for the drop down which is also working, but I can't work out how to get an object of type Category from my drop down and add it to the category list in my bean.

Here is the section of my JSF I'm trying to achieve this from:

<table>
<tr>
    <th class="textRight">Choose Category</th>
    <td>
        <h:selectOneMenu id="currentCategory">
            <f:selectItems value="#{serviceWeb.listCategories()}" />
        </h:selectOneMenu>
    </td>
    <td>
        <h:commandButton id="addCategory" value="Add" 
                         action="element.categories.add(#{currentCategory.value})"  />
    </td>
</tr>
</table>

I know this doesn't work, I get the error:

action="element.categories.add(#{currentCategory.value})" Not a Valid Method Expression

to explain, there is no backing bean for this menu item, I'm trying to get the value from the component itself.

So I guess you can't do it this way, but how do you do it?

Is it possible?

Ry-
  • 218,210
  • 55
  • 464
  • 476
Link19
  • 586
  • 1
  • 18
  • 47

1 Answers1

2

Bind the component to the view (which will in case of <h:selectOneMenu> resolve to an instance of HtmlSelectOneMenu) and use UIInput#getValue() as action method argument and fix your invalid EL syntax.

<h:selectOneMenu binding="#{currentCategory}">
    <f:selectItems value="#{serviceWeb.listCategories()}" />
</h:selectOneMenu>
<h:commandButton value="Add" action="#{element.categories.add(currentCategory.value)}" />
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Interesting, element.categories is resolving as a string before add is called on it. Oh I know why, it's because it's a Set. I'll have to write an add method in the element class. – Link19 Feb 21 '12 at 16:44
  • Works just for me. Perhaps you're using a buggy 3rd party EL resolver. – BalusC Feb 21 '12 at 16:49
  • Works for you with sets? Now I've added the addCategory() method to element I get another error because the currentCategory.value is also resolving to a string. I'm sure there's no 3rd party ELResolver. – Link19 Feb 21 '12 at 16:58
  • That's a different problem which is caused by the way how you populated the list behind `listCategories()`. Apparently it contains non-standard Java types as values, you'd need to create a `Converter`. The values are passed and obtained as HTTP request parameters which can be `String` only. Rightclick page in browser and check the generated ` – BalusC Feb 21 '12 at 17:01
  • Yes, funnily enough I used your article here: http://balusc.blogspot.com/2007/09/objects-in-hselectonemenu.html to do that. I would have thought the fact that I was trying to add Category objects from the drop down was implicit in the fact that I was calling add() on a collection? – Link19 Feb 21 '12 at 17:03
  • I assume that the converter would kick in when I tried to do get the value from my menu, if not how do I invoke the converter I already have in place from the "action" of my button. – Link19 Feb 21 '12 at 17:11
  • No, what happens here is that the component value is been set based on the HTTP request parameter. The converter needs to be attached to the `` by the usual means (by either the `converter` attribute or a nested `` tag). The `getAsString()` will be invoked when the complex object needs to be converted to a string representing the unique option value. the `getAsObject()` will be invoked when the string representing the unique option value needs to be converted back to the complex object. – BalusC Feb 21 '12 at 17:13
  • So how do I invoke the converter from my action="" ? – Link19 Feb 21 '12 at 17:21
  • Once again: You don't. Just attach the converter to the `` by the usual means. – BalusC Feb 21 '12 at 17:22
  • Oh ok, sorry, I missunderstood what you meant. I was using the tag rather than an ID. thank you. – Link19 Feb 21 '12 at 17:31
  • Oh, when you're on JSF2, you can also use `@FacesConverter(forClass=Category.class)` annotation on the `Converter` implementation, this way you don't need to register it in `faces-config.xml`. – BalusC Feb 21 '12 at 17:37
  • Well using "for-class" clearly wasn't working as when I changed it using id it now works.......well it gets in to my converter but the bean I tried to wire in isn't being picked up, but that's another issue for another day.. – Link19 Feb 21 '12 at 17:52
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/8061/discussion-between-glen-lamb-and-balusc) – Link19 Feb 22 '12 at 11:08