Martin Marinschek wrote:

have you tried to set the "immediate" attribute on the ui-input component?

Yes. I have immediate="true" set for the <h:selectOneMenu> elements and in the event handler I have it updating the selected value and then jumping to the renderResponse() phase to bypass validation. The problem is that the backing bean is request scoped and the previously set value for the first <h:selectOneMenu> does not get set again in the backing bean. So the only way I can think to get that value is to use the getExternalContext().getRequestParameterMap(). Here's the JSF tags so you can get a better idea of what is going on cause I don't think I'm getting my thoughts across very clearly.

               <h:panelGroup>
<h:outputLabel for="organization" value="Organization" /> <h:selectOneMenu id="organization" value="#{courseHandler.selectedOrganization}" valueChangeListener="#{courseHandler.handleOrganizationChanged}" onchange="submit()" immediate="true">
                       <f:selectItem itemValue="" />
<f:selectItems value="#{organizationHandler.organizationChoices}" />
                   </h:selectOneMenu>
               </h:panelGroup>
               <br />
               <h:panelGroup>
                   <h:outputLabel for="department" value="Department" />
<h:selectOneMenu id="department" value="#{courseHandler.selectedDepartment}" valueChangeListener="#{courseHandler.handleDepartmentChanged}" onchange="submit()" immediate="true">
                       <f:selectItem itemValue="" />
<f:selectItems value="#{courseHandler.departmentChoices}" />
                   </h:selectOneMenu>
               </h:panelGroup>
               <br />
               <h:panelGroup>
                   <h:outputLabel for="instructors" value="Instructors" />
<h:selectManyListbox id="instructors" value="#{courseHandler.selectedInstructors}"> <f:selectItems value="#{courseHandler.contactChoices}" />
                   </h:selectManyListbox>
               </h:panelGroup>

Now the selectItems for the department depend on the selected value of the organization and the selectItems for the instructors list depends on the selected value for the departments. What's happening is that when a user selects the organization the department list gets populated just fine. When they select the department, the instructors list gets populated fine, but the departments list comes up empty because the value for the organization is never set in the backing bean because the update model phase is also bypassed. The only ways I can think to fix this is to make the backing bean session scoped so that the selected organization is persisted across requests. But that makes me nervous cause it seems error prone. The only other way to do it is to use the getExternalContext().getRequestParameterMap() and lookup the value for the selected organization in the handleDepartmentChanged() event handler. But that seems like a bad idea because it means I have to know the id of the element ahead of time, which I think is just sloppy design.

I'll probably wind up switching to a session scoped backing bean if I have to. But that raises all sort of other problems in other areas that I'm not entirely sure how to work around. I guess I could move stuff that needs to be request based like the dynamic choice elements to be request scoped and keep the current working object session scoped or something like that.

Does that sound like a decent approach or is there a better way?

Thanks again,
Rich

regards,

Martin

On 6/12/05, Richard Wallace <[EMAIL PROTECTED]> wrote:
I understand all that you've said and am using some application scoped
beans for global select items that don't change.  The problem is that
the list of items that I'm working with now are database backed and are
likely to change often.  I can maybe cache the top level select list
items, the organizations and update it when an organization is added or
updated.  But the others, the list items for departments and personnel
are dependent on the selected organization so there's no way to cache
them.

What about my other questions?  When the second select list, the
department, selected value changes and the page is submitted for
immediate event handling, it seems the only way to avoid validation
_and_ have the selected organization set in the backing bean is to
lookup the value myself using the
FacesContext.getExternalContext().getParameterMap().  Is there a better
way to accomplish this?

Thanks for the feedback,
Rich
Craig McClanahan wrote:

One thing to remember is that you are *not* limited to referencing a
single backing bean.  Using a request scope backing bean corresponding
to the page is fine ... but quite often, the lists of select items are
fairly constant, and you'd *really* like to build them only once,
right?

In the Shale <http://struts.apache.org/shale> "use cases" example
application, there is an illustration of the technique I prefer for
this ... bind select lists to a property on an application scoped
managed bean (if they are common to all users) or on a session scoped
managed bean (if they are specific to a user).  The example includes
"select locale" use case, which includes a dropdown like this:

  <h:selectOneListbox id="locale"
      value="#{locale$select.locale}">
          <h:selectItems value="#{domains.supportedLocales}"/>
  </h:selectOneListbox>

where "locale$select" is my request scoped managed bean for this page,
and "domains" is an application scoped managed bean that includes this
method:

  public SelectItem[] getSupportedLocales();

Inside this method, you have a number of alternative strategies
available ... and you can change your choice without callers having a
clue :-).  Consider among other options:

* Lazily instantiating the list the first time someone calls this method.

* Using a ServletContextListener to load up the appropriate data before
the first request is received.

* Either of the above two techniques, plus a timer thread to erase the
cached value after a given amount of time (to pick up the changes that
occasionally occur, without having to restart the app).

* Either of the above two techniques, plus embedded logic that does a
relatively cheap database access to determine whether the data has
changed, and refreshes the list first.

Doing this sort of logic on every request is quite likely a waste of
resources.  Strive to minimize the number of times you do things like
"create a SelectItems array containing the 50 state abbreviations and
names" :-).  That's the sort of thing I would want to do just once
:-).

Craig McClanahan


On 6/11/05, Richard Wallace <[EMAIL PROTECTED]> wrote:


I just thought that I should also mention that my backing bean is a
request scoped object.  So another solution is to switch this to a
session based backing bean, but my backing bean is where the select
items for organizations, departments and contacts for the list boxes and
drop-down menus are generated.  I would like to be able to cache those
for the life of the request but they shouldn't be cached across requests
since they could change at any time.

What's the best practice for these backing beans?  My design is pretty
much following the design ideas in a couple of articles I've read where
the backing bean contains the current selected object and the JSF pages
bind with value="#{contactHandler.currentContact.firstName}" for
example.  Is it better to have this backing bean be session scoped or
request scoped?

Richard Wallace wrote:



Richard Wallace wrote:



So what do I need to do to fix this?  One idea is to try and find the
value that JSF will use in the form and use that if there is one and
then otherwise use the backing beans value when I'm generating the
department choices.  Seems kind of hacky since that's one of the
things that JSF is supposed to do for you is provide the form
values.  I'm also not certain how to get the values that JSF is going
to use in the forms without having it update the model values.


Well, I figured this part out at least.  I can use the
FacesContext.getExternalContext ().getRequestParameterMap(), but then
I'd need to know the key of the form and form element to be able to
lookup the value.  Obviously, not an ideal solution.



Another idea is if I can somehow avoid doing the validation some
other way.  That's really the only reason I need to do the event
processing right away and then skip to the rendering phase.  But I've
looked and there doesn't seem to be another way of bypassing validation.


Well, I've looked around and this doesn't seem possible.  Unless I can
do something with PhaseListeners, but I don't see how.

Please help!

Thanks,
Rich




Reply via email to