Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Passing values between views  RSS feed

 
Tom Mains
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
New to the forum and JSF but not Java.

I am at a loss as how to pass the value of a field in a database from one view to another.

I currently have a list of members drawn from a database.

The members view is a list of members. From the list the user clicks view button to view a particular member. This is achieved by using a inputHidden tag with the value of the list of members in a data table.

<h:dataTable value="#{controllerBean.listAllMembers()}" var="mem">

<h:form id="inputForm">
<h:inputHidden id="idToken" value="#{mem.id}" />

in the RequestScoped bean I am able to use FacesContext to extract the value of idToken from the requestParameters and create the view for the particular member.

One field in the member view I would like to toggle - "Y" to "N" or vice versa via a commandButton. The issue is I can find no way of passing this single value back to the bean as is.


The issue is the value is displayed within the output text - how to pass the value into the inputHidden value.

 
Tim Holloway
Bartender
Posts: 18531
61
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
JSF is a Model/View/Controller system. Ideally the View is NOT a container for logic, it's a template for display. Thus, constructs like:



are bad practice. Also, backing beans are not Controllers. They are Models. Controllers are code that synchronize the data in Model and View, and that's done by in JSF by pre-supplied logic, not user-written code. Action methods are business methods, not Controller methods. You don't use FacesContext to get data values, because the Controllers built into JSF automatically maintain the data values in the Model without user code being required.

The answer to "passing values between views" is that you shouldn't. JSF was designed to keep the values in the server (stored in, or accessed by Models), and the View is just where you display or edit it.

So let's re-construct your example in JSF terms. I'm going to state your problem as I see it in simple terms. I've probably missed something, but I think that I'm close enough that you can see the application in terms of what you really want.

Let's assume you have a table display and each row of the display contains an item whose status is either Active or Inactive. You put a button on the table row to toggle it. OK, I don't think this is precisely what you're saying, but I think it's close enough.

In JSF terms, if you want to display tabular data, the go-to tag is the "h:dataTable" tag. So far, so good.

But you went astray with your attempt to access the rows programmatically. Here's the intended syntax for JSF:



Notice that "listAllMembers()" - a function call is now "allMembers" - a property reference.

The corresponding "getAllMembers()" method in the backing bean (which, incidentally, cannot be Request-scoped) could simply return a List of rows. But if it does, then you lose that essential data reference point you're asking about.

So instead, have the backing bean construct a JSF wrapper for the list - a ListDataModel. The wrapper object serves as a fa├žade for the List, but decorates it with essential properties that help JSF - and you - keep track of what's going on. It's so essential, in fact, that if you don't use a DataModel and use a raw collection as your backing bean's value object, an anonymous DataModel will automatically be constructed and used to wrap your collection. But you won't be able to access it yourself.

A DataModel is easy to use. Either wrap your data at construction time:


Or manually wrap (or, if need be, re-wrap)


When you wrap a List, it stays wrapped. If you make changes to the List, you do NOT have to re-wrap it. Only if you want your datamodel to reference a completely different list would you re-wrap (with the new list).

If you're confused, take a look at this: http://www.tutorialspoint.com/jsf/jsf_using_datamodel.htm

OK. Now we've got the data model for the backing bean with its table sub-model. HOW do you know which row is being toggled?

In an action method or AJAX listener fired by clicking the toggle button, that's how.

The action code can use the getAllMembers().getRowData() method. It references the decorator data in the DataModel to determine which row the event was fired from. If you don't want/need the row data and only are about its index, use the getRowIndex() method.

That's all there is to it. You can do something like this:



Note that this example expects 2 properties in the row. The actual binary state value and the display value corresponding to it. In a database, you probably wouldn't have done that, but since the row is a UI model, not a data model, you can take the data model object and decorate it with the extra information to make a UI row model object, collect those objects into a list and wrap the list. So you then would have:

dataModel (wraps) -> List(rows), each row (decorates) -> database row.

That sort of thing is something I do a lot. I usually use checkboxes, not buttons-and-labels, and checkboxes MUST be backed but boolean-typed properties. But most databases - and consequently most ORM models don't have native boolean types. So the row decorator translates the "Y/N", "T/F" or whatever that's in the database to a boolean that the JSF UI can render as a checkbox.
 
Tom Mains
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
:thumbup:

Thanks for the clear and precise information. Was able to implement what I required. Whether it is adheres to convention or not. it has been a valuable lesson.

Thanks again.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!