• Post Reply Bookmark Topic Watch Topic
  • New Topic

button and commandButton confusion

 
Tom Fulton
Ranch Hand
Posts: 96
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have to admit that I'm getting more and more confused about the behavior I'm seeing in <h:commandButton> vs. <h:button> components. I understand the intent: commandButton (and commandLink) submit the form, always do a POST and render as an <input type="submit">. button (and link) don't submit the form, do a GET and render as an <input type="button">.

That being said, I have a dataTable with rows that I'd like to select and perform work on. Let's say I'd like to Edit an existing row, or Delete a row. I'd like to do each of these things via a button, a request-scoped bean and view parameters. So my dataTable looks roughly like this:

This actually works reasonably well. In the target page, I have view parameters and an <f:event> for preRenderView that takes the parameter, loads up the data, and displays it on the page.
The problem occurs when I add another button to the row. If I use an <h:button>, the display of the rows gets totally hosed and nothing works. If I use an <h:commandButton>, it displays correctly, but pressing the commandButton causes it to attempt to execute the edit outcome method for that row, and throws a NullPointerException because the parameter isn't being populated.

I am beginning to suspect that I'm just trying to do something that isn't even reasonable. Specifically, I'm attempting to perform work on the server side that arguably should be done as a POST. The Edit, one could argue, is just passing a parameter, and the "page action" <f:event> is doing the work on the preRenderView. Is there a way to accomplish my goal, or should I just abandon the attempt? And why is it behaving so psychotically?
 
Tim Holloway
Bartender
Posts: 18415
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The h:button is a recent addition and is part of a set of improvements that make JSF more GET-friendly.

The original way to use an "edit" button in a table can be seen illustrated in a very old, but still essentially useful article "JSF For NonBelievers" at IBM DeveloperWorks.

In a nutshell, you use a DataModel object as the Model object for the dataTable. JSF1 required a DataModel. JSF2 will automatically construct one from an ordered collection (List or array), but it will be anonymous, so you won't be able to access useful functions if you do that.

In the commandButton's action method, you can use the dataModel's getRowData to obtain the object that backs the selected row, or the getRowIndex if you just want its row number.

Armed with this information, you can use JSF navigation to handle the detail edit. Here's a sample:



In this example, the thingEditor detail edit backing bean was injected as a managed property into the thingTableList class that contains the above method. That, however, requires thingEditor to be session scoped, which can be annoying. There are alternatives, however.

Any object containing a DataModel must have at least View Scope. If it's put in Request scope, the DataModel gets destroyed and re-created from scratch on each request, and loses essential context information. This is one of the reasons why Request scope is almost totally useless in JSF.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!