You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Pa...@anicasystem.com.pl on 2007/08/09 16:02:39 UTC

[JSF] Custom component - commandLink

Hi, 
I'm developing some simple custom component, and I'm facing a problem I 
cannot resolve and understand, so I will really appreciate any help.

I have this piece of code:

public void encodeBegin(FacesContext c) throws IOException {
        HtmlCommandButton b = (HtmlCommandButton) 
context.getApplication().createComponent(HtmlCommandButton.COMPONENT_TYPE);
      b.setValue("Click me");
      b.encodeBegin(context);
      b.encodeChildren(context);
      b.encodeEnd(context);
}

And with above code everything is great, the button renders and when I 
click it, the 

public void decode(FacesContext context) 

method is called... But. If I change HtmlCommandButton to HtmlCommandLink 
something strange happens. The link is created and renders as well, 
but when I click it, the decode method is not called at all.

Is there any difference between handlig those two components?
Thanks in advance!

-- 
greetings
Paweł Czerwiński


Re: [JSF] Custom component - commandLink

Posted by Pa...@anicasystem.com.pl.
Thanks for your help, everything works now!

-- 
regards
Paweł Czerwiński



"Andrew Robinson" <an...@gmail.com> wrote on 2007-08-09 
17:04:25:

> You have a few problems with that code.
> 
> 1) You should set the parent of the component, this causes issues with
> many components
> 2) You should mark the component as transient, which should be done
> for components that will not be saved into the component tree
> 3) You should set an ID of the component, which should be done for all
> components
> 4) Your component is not preserved, so you have to perform the decode 
yourself
> 5) Even with the decode, you have to be careful as the event will be
> tied to that component, which is temporary.
> 6) You shouldn't call encodeChildren on a component without first
> checking the getRendersChildren flag of the component
> 
> Try this:
> 
> public class MyRenderer extends Renderer {
>   public void decode(FacesContext context, UIComponent component) {
>     if (!component.isRendered()) {
>       return;
>     }
>     createButton(ctx, component).decode(context);
>   }
> 
>   public void encodeBegin(FacesContext ctx, UIComponent component) {
>     if (!component.isRendered()) {
>       return;
>     }
>     HtmlCommandButton b = createButton(ctx, component);
>     b.setValue("Click me");
>     RendererUtils.renderChild(ctx, component);
>   }
> 
>   private HtmlCommandButton createButton(FacesContext ctx,
>     UIComponent component) {
>      HtmlCommandButton b = (HtmlCommandButton)ctx.getApplication()
>       .createComponent(HtmlCommandButton.COMPONENT_TYPE);
>     b.setId(ctx.getViewHandler().getViewRoot().createUniqueId());
>     b.setTransient(true);
>     b.setParent(component);
>     return b;
>   }
> }
> 
> Since the FacesEvent has a reference to its component, the event
> should work fine. If you need to do anything special on one of those
> events, you will need to override your component's queueEvent method,
> so you can trap events being queued by the button during the decoding.
> 
> -Andrew
> 
> 
> On 8/9/07, Pawel.Czerwinski@anicasystem.com.pl
> <Pa...@anicasystem.com.pl> wrote:
> >
> > Hi,
> > I'm developing some simple custom component, and I'm facing a problem 
I
> > cannot resolve and understand, so I will really appreciate any help.
> >
> > I have this piece of code:
> >
> > public void encodeBegin(FacesContext c) throws IOException {
> >         HtmlCommandButton b = (HtmlCommandButton)
> > 
context.getApplication().createComponent(HtmlCommandButton.COMPONENT_TYPE);
> >       b.setValue("Click me");
> >       b.encodeBegin(context);
> >       b.encodeChildren(context);
> >       b.encodeEnd(context);
> > }
> >
> > And with above code everything is great, the button renders and when I 
click
> > it, the
> >
> > public void decode(FacesContext context)
> >
> > method is called... But. If I change HtmlCommandButton to 
HtmlCommandLink
> > something strange happens. The link is created and renders as well,
> > but when I click it, the decode method is not called at all.
> >
> > Is there any difference between handlig those two components?
> > Thanks in advance!
> >
> > --
> >  greetings
> >  Paweł Czerwiński
> >
> >

Re: [JSF] Custom component - commandLink

Posted by Andrew Robinson <an...@gmail.com>.
You have a few problems with that code.

1) You should set the parent of the component, this causes issues with
many components
2) You should mark the component as transient, which should be done
for components that will not be saved into the component tree
3) You should set an ID of the component, which should be done for all
components
4) Your component is not preserved, so you have to perform the decode yourself
5) Even with the decode, you have to be careful as the event will be
tied to that component, which is temporary.
6) You shouldn't call encodeChildren on a component without first
checking the getRendersChildren flag of the component

Try this:

public class MyRenderer extends Renderer {
  public void decode(FacesContext context, UIComponent component) {
    if (!component.isRendered()) {
      return;
    }
    createButton(ctx, component).decode(context);
  }

  public void encodeBegin(FacesContext ctx, UIComponent component) {
    if (!component.isRendered()) {
      return;
    }
    HtmlCommandButton b = createButton(ctx, component);
    b.setValue("Click me");
    RendererUtils.renderChild(ctx, component);
  }

  private HtmlCommandButton createButton(FacesContext ctx,
    UIComponent component) {
     HtmlCommandButton b = (HtmlCommandButton)ctx.getApplication()
      .createComponent(HtmlCommandButton.COMPONENT_TYPE);
    b.setId(ctx.getViewHandler().getViewRoot().createUniqueId());
    b.setTransient(true);
    b.setParent(component);
    return b;
  }
}

Since the FacesEvent has a reference to its component, the event
should work fine. If you need to do anything special on one of those
events, you will need to override your component's queueEvent method,
so you can trap events being queued by the button during the decoding.

-Andrew


On 8/9/07, Pawel.Czerwinski@anicasystem.com.pl
<Pa...@anicasystem.com.pl> wrote:
>
> Hi,
> I'm developing some simple custom component, and I'm facing a problem I
> cannot resolve and understand, so I will really appreciate any help.
>
> I have this piece of code:
>
> public void encodeBegin(FacesContext c) throws IOException {
>         HtmlCommandButton b = (HtmlCommandButton)
> context.getApplication().createComponent(HtmlCommandButton.COMPONENT_TYPE);
>       b.setValue("Click me");
>       b.encodeBegin(context);
>       b.encodeChildren(context);
>       b.encodeEnd(context);
> }
>
> And with above code everything is great, the button renders and when I click
> it, the
>
> public void decode(FacesContext context)
>
> method is called... But. If I change HtmlCommandButton to HtmlCommandLink
> something strange happens. The link is created and renders as well,
> but when I click it, the decode method is not called at all.
>
> Is there any difference between handlig those two components?
> Thanks in advance!
>
> --
>  greetings
>  Paweł Czerwiński
>
>