On Fri, 2006-01-20 at 13:37 +1300, Simon Kitching wrote:
> On Fri, 2006-01-20 at 01:14 +0100, Jesse Alexander (KBSA 21) wrote:
> > We solved the problem rendering an icon with a commandLink.
>
> Yep, good point. I guess the code looks like this:
>
> <h:commandLink ..>
> <f:param name="recordId" value="#{row.key}"/>
> <h:graphicImage ..../>
> </h:commandLink>
>
> f:param resolves its value at render time, so this is fixed regardless.
>
Hmm.. on further thought there may be a problem with this. An
h:commandLink doesn't generate a GET command when clicked, as that
doesn't integrate well with JSF lifecycles. Instead, it generates a POST
just like a button does, and encodes the link's id in a hidden field to
indicate to JSF which component caused the submit.
When a UIData (table) component renders links in a table, it creates an
id for each link indicating the row# it is for.
When the table processes submitted parameters for its children, it does:
for each object in the datamodel
set "current object" to be that object in the datamodel
tell children to decode
If the link clicked is in row N, and the new datamodel size fetched has
less than N rows, the click will be ignored and the current page just
refreshed. So you'll never get the *wrong* object, but you might get a
selection ignored.
At least that's what I think will happen; UIData is rather complicated
so I could be wrong.
I still think my earlier recommendation of saving the list at render,
restoring it at "restore view" then clearing it (or refetching it)
before the render phase [if you care about stale data] is the correct
solution (though possibly not the most efficient).
Possibly the data stored could be a cut-down variant of the data used to
render rather than the actua objects; just the data for input fields are
actually needed. At an extreme (in the case where all fields are output
except the link), it might be possible to just save the size of the
datamodel, then when the model is requested during validation phase just
return an array of null objects of the appropriate size.
The problem is triggering the clear/refetch of the datamodel just before
the render phase. I suggested using the get method and keeping track of
the current state so the change from before-render to in-render can be
detected. It would be even easier, however, if the backing bean could
get a callback at the right phase. PhaseListeners aren't that easy to
work with for this purpose, however: they are app-wide, not per-request.
They do have access to the FacesContext for the current request, but
it's not trivial to find the associated beans from that.
It looks like if you use Shale and your backing bean implements the
ViewController interface then a preRender() method is called at exactly
the right time to do this. NB: haven't tried this myself.
http://struts.apache.org/struts-shale/index.html
Regards,
Simon