Another resource to consider when writing facelets componenthandlers
and taghandlers is the facelets wiki. There's a few examples
available there. 90% of the time, it's simply a matter of applying a
MethodRule since method signatures are the one thing that facelets
cannot autodetect :-)
On 12/12/06, Martin Grotzke <[EMAIL PROTECTED]> wrote:
Hello Mike,
On Mon, 2006-12-11 at 15:37 -0500, Mike Kienenberger wrote:
> I think you made the facelets tag handler harder that necessary. Not
> sure about the "void.class" syntax below, but you can probably figure
> out the correct syntax.
Thanx a lot, this is a great simplification! (and the void.class is
correct :))
I wrote the tag handler according to what I've seen in the facelets
sources, knew (read) nothing about MethodRule :)
Thanx again,
cheers,
Martin
>
>
> private static final String ACTION_LISTENER_ATT_NAME =
> "toggleDetailActionListener";
>
> public final static Class[] ACTION_LISTENER_SIG = new Class[] {
> ActionEvent.class };
> protected final static MethodRule actionListenerTagRule
> = new MethodRule(ACTION_LISTENER_ATT_NAME, void.class,
> ACTION_LISTENER_SIG);
>
> public CustomHtmlDataTableHandler(ComponentConfig config) {
> super( config );
> }
>
> protected MetaRuleset createMetaRuleset(Class type)
> {
> MetaRuleset m = super.createMetaRuleset(type);
>
> m.addRule(actionListenerTagRule);
>
> return m;
> }
>
> On 12/11/06, Martin Grotzke <[EMAIL PROTECTED]> wrote:
> > On Mon, 2006-12-11 at 20:37 +0100, Martin Grotzke wrote:
> > > On Mon, 2006-12-11 at 09:44 -0700, Andrew Robinson wrote:
> > > > "When myBean.myModel.myOptions is invoked the first time, I do some
> > > > lazy
> > > > initialization, this might cause errors..."
> > > >
> > > > I would recommend that you load this data in the on load method of
> > > > your page. This way, if it fails, you can handle the error in any way
> > > > you want, including redirecting to an error page.
> > > I cannot do this, because I have to initialize the detailStamps of
> > > all rows separately: the details of one item cause several backend
> > > requests that might cost money, and they definitively need time
> > > to return (several seconds per request).
> > >
> > > Now I wrote a CustomHtmlDataTable (extending HtmlDataTable) that
> > > provides an additional MethodBinding "toggleDetailActionListener".
> >
> > Btw, I just posted the complete example here:
> >
http://www.javakaffee.de/blog/2006/12/11/how-to-add-a-new-attribute-to-an-existing-jsf-component-using-facelets/
> >
> > Perhaps it's useful for someone...
> >
> > Cheers,
> > Martin
> >
> >
> > >
> > >
> > > The toggleDetail method is extended so that it invokes also the method
> > > binding if it's provided.
> > >
> > > The hardest thing was to write the facelets MetaTagHandler that sets
> > > the attribute on the CustomHtmlDataTable:
> > >
> > > public final class CustomHtmlDataTableHandler extends ComponentHandler {
> > >
> > > public CustomHtmlDataTableHandler(ComponentConfig config) {
> > > super( config );
> > > }
> > >
> > > protected MetaRuleset createMetaRuleset(Class type) {
> > > return super.createMetaRuleset(type).addRule(
ActionSourceRule.Instance );
> > > }
> > >
> > > static final class ActionSourceRule extends MetaRule {
> > >
> > > private static final String ACTION_LISTENER_ATT_NAME =
"toggleDetailActionListener";
> > >
> > > public final static Class[] ACTION_LISTENER_SIG = new Class[] {
ActionEvent.class };
> > >
> > > final static class ActionListenerMapper extends Metadata {
> > >
> > > private final TagAttribute attr;
> > >
> > > public ActionListenerMapper(TagAttribute attr) {
> > > this.attr = attr;
> > > }
> > >
> > > public void applyMetadata(FaceletContext ctx, Object
instance) {
> > > ((CustomHtmlDataTable) instance)
> > > .setToggleDetailActionListener( new
LegacyMethodBinding(this.attr
> > > .getMethodExpression(ctx, null,
> > >
ActionSourceRule.ACTION_LISTENER_SIG)));
> > > }
> > >
> > > }
> > >
> > > public final static ActionSourceRule Instance = new
ActionSourceRule();
> > >
> > > public ActionSourceRule() {
> > > super();
> > > }
> > >
> > > public Metadata applyRule(String name, TagAttribute attribute,
> > > MetadataTarget meta) {
> > > if (meta.isTargetInstanceOf(CustomHtmlDataTable.class)) {
> > >
> > > if (ACTION_LISTENER_ATT_NAME.equals(name)) {
> > > return new ActionListenerMapper(attribute);
> > > }
> > > }
> > > return null;
> > > }
> > > }
> > >
> > > }
> > >
> > >
> > > I hope this is basically the correct approach...
> > >
> > > Cheers,
> > > Martin
> > >
> > >
> > >
> > > > Use one of these technologies:
> > > >
> > > > 1) JBoss-Seam. Set the action to run in the pages.xml file. Example:
> > > >
> > > > <page view-id="/index.xhtml"
> > > > action="#{welcomeBean.onLoad}" />
> > > >
> > > > 2) On-load from jsf-comp:
> > > > http://jsf-comp.sourceforge.net/components/onload/index.html
> > > >
> > > > 3) or use Shale (I have no experience with this one):
> > > > http://shale.apache.org/shale-view/index.html
> > > >
> > > > -Andrew
> > > >
> > > > On 12/11/06, Martin Grotzke <[EMAIL PROTECTED]> wrote:
> > > > On Mon, 2006-12-11 at 10:29 -0500, Simon Lessard wrote:
> > > > > Hello Martin,
> > > > >
> > > > > Can you provide a mopre explicit example of the use case
> > > > please?
> > > > Sorry for the few words, if you think about a problem for
> > > > several days
> > > > to you it seems just too clear ;)
> > > >
> > > > What I have is a datatable in a template with the detailStamp
> > > > facet:
> > > >
> > > > <table jsfc="t:dataTable"
> > > > ...
> > > > value="#{myBean.myModel}"
> > > > var="myItem"
> > > > varDetailToggler="detailToggler">
> > > >
> > > > ... some columns ...
> > > >
> > > > <span jsfc="f:facet" name="detailStamp">
> > > > <ui:include src=" itemdetails.xhtml">
> > > > <ui:param name="item"
> > > > value="#{myItem}"/>
> > > > </ui:include>
> > > > </span>
> > > > </table>
> > > >
> > > > The itemdetails.xhtml displays details to the item, e.g. it
> > > > iterates
> > > > over some detail options like the following:
> > > >
> > > > <ui:repeat var="option" value="#{item.myOptions}">
> > > > #{option.description}
> > > > </ui:repeat>
> > > >
> > > > So the the myBean.myModel.myOptions method is requested when
> > > > the detailStamp
> > > > is displayed for one item, this method is invoked when
> > > > rendering happens.
> > > >
> > > > When myBean.myModel.myOptions is invoked the first time, I do
> > > > some lazy
> > > > initialization, this might cause errors...
> > > >
> > > > I do not see how I could do the processing in the invoke
> > > > application, because
> > > > the detailStamp is shown via HtmlDataTable.toggleDetail, which
> > > > is invoked
> > > > during invoke-application, but there's no possibility of
> > > > specifying a listener
> > > > that is invoked when toggleDetail is invoked...
> > > >
> > > > I hope this clarifies the problem a little bit, if s.th. is
> > > > missing please
> > > > let me know!
> > > >
> > > > Thanx a lot,
> > > > cheers,
> > > > Martin
> > > >
> > > >
> > > >
> > > > > Why can't you do the processing in the invoke application
> > > > phase?
> > > > > Without more details, all I could suggest is to use a render
> > > > response
> > > > > phase listener and add your logic in the beforePhase
> > > > method.
> > > > >
> > > > >
> > > > > Regards,
> > > > >
> > > > > ~ Simon
> > > > >
> > > > > On 12/11/06, Martin Grotzke <[EMAIL PROTECTED]>
> > > > wrote:
> > > > > Hi all,
> > > > >
> > > > > I have a case where I perform some logic during the
> > > > > RENDER_RESPONSE
> > > > > phase where an error might occurs and I want to
> > > > display some
> > > > > error
> > > > > message - which is unfortunately not displayed
> > > > directly. But
> > > > > with the
> > > > > next request/response the error message is
> > > > displayed. I asume
> > > > > that this
> > > > > is the case because the h:messages component is
> > > > already
> > > > > rendered - so
> > > > > the behavior should basically be correct.
> > > > >
> > > > > Do you have any suggestions how to handle this?
> > > > >
> > > > > The concrete case is when the details of a dataTable
> > > > (facet
> > > > > detailStamp)
> > > > > are displayed - just comes into my mind to use a
> > > > > CustomHtmlDataTable
> > > > > component that overrides the toggleDetail method...
> > > > What do
> > > > > you think?
> > > > >
> > > > > Thanx in advance,
> > > > > cheers,
> > > > > Martin
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > --
> > > > Martin Grotzke
> > > > http://www.javakaffee.de/blog/
> > > >
> > > >
> > > >
> > --
> > Martin Grotzke
> > http://www.javakaffee.de/blog/
> >
> >
> >
>
--
Martin Grotzke
http://www.javakaffee.de/blog/