Matt, Craig, Martin and Jesse told you some workarounds to your problems.
In this article Hans Bergsten wrote about JSP *and* JSF. http://www.onjava.com/pub/a/onjava/2004/06/09/jsf.html Perhaps it is usful for you to read it. Nice day, Matthias > -----Original Message----- > From: Matt Raible [mailto:[EMAIL PROTECTED] > Sent: Thursday, December 02, 2004 7:53 AM > To: MyFaces Discussion > Subject: Re: h:outputLabel - validation and colons > > > Thanks David - much appreciated. Unfortunately, in my testing the > "input" is always null b/c the label comes before the component it's > for. If I move the label after the field, then the asterisk renders > properly. Am I missing something? > > Thanks, > > Matt > > David Geary wrote: > > > Le Dec 1, 2004, � 9:42 PM, David Geary a �crit : > > > > [snip] > > > >>> Hmmm, sounds like I have to have a getter method for each > form field > >>> on my managed bean? What a pain? > >>> Isn't there a way to look up if the field is required > and just add > >>> a * - a solution that's generic for all outputLabel's? > I'm willing > >>> to hack source code or create components if I need to - I > just need > >>> to know 2 things: > >>> > >>> 1. Yes/No - if I have to hack the source to make the > dynamic lookup > >>> possible? > >> > >> > >> No hacking is required. > >> > >>> 2. Where do I hack the source? I'm guessing there's some way to > >>> lookup the validation metadata for the inputs and use > that data in > >>> the labels. > >> > >> > >> You could implementing a replacement for the Label renderer: > >> > >> 1. In a renderer method such as encodeBegin(), get the value of the > >> renderer's component (encodeBegin is passed the component. > Call the > >> component's getValue method). In this case, the component is the > >> label and the value is the id of the labeled component. > >> > >> 2. Get a reference to the labeled component. In a JSF component > >> hierarchy, any component can find any other component in the > >> hierarchy with the findComponent(String) method, where the > String is > >> the component's id. So the label can find the labeled component. > >> > >> 3. Find out if the labeled component is required. Input components > >> implement the editableValueHolder interface, which defines an > >> isRequired method. > >> > >> 4. Render according to whether the labeled component is required. > >> > >> > >> david > > > > > > I went ahead and implemented this. After replacing the > standard Label > > renderer, this... > > > > <h:outputLabel for="name" value="#{msgs.namePrompt}"/> <h:inputText > > id="name" value="#{registerForm.name}" /> > > > > ...has a plain prompt, whereas the following has an asterik > prepended > > to the prompt: > > > > <h:outputLabel for="name" value="#{msgs.namePrompt}"/> <h:inputText > > id="name" value="#{registerForm.name}" required="true"/> > > > > Here's how it works. First, add this to your faces config file: > > > > <faces-config> > > ... > > <render-kit> > > <description>Some replacements for the standard > > renderers</description> > > <renderer> > > <description>Replacement renderer for > > h:outputLabel</description> > > <component-family>javax.faces.Output</component-family> > > <renderer-type>javax.faces.Label</renderer-type> > > <renderer-class>renderers.LabelRenderer</renderer-class> > > </renderer> > > </render-kit> > > </faces-config> > > > > Because we didn't specify a renderkit name, JSF modifies the default > > renderkit by replacing the javax.faces.Label type renderer with our > > custom version. > > > > Here's the renderer class: > > > > package renderers; > > > > import java.util.Map; > > import javax.faces.component.UIComponent; > > import javax.faces.component.UIInput; > > import javax.faces.context.FacesContext; > > import javax.faces.context.ResponseWriter; > > import javax.faces.render.Renderer; > > > > // Renderer for the Label components > > > > public class LabelRenderer extends Renderer { > > public boolean getRendersChildren() { > > return false; > > } > > > > public void encodeBegin(FacesContext context, > UIComponent component) > > throws java.io.IOException { > > ResponseWriter writer = context.getResponseWriter(); > > writer.startElement("label", component); > > > > String styleClass = (String) > > component.getAttributes().get("styleClass"); > > if (styleClass != null) > > writer.writeAttribute("class", styleClass, null); > > > > Map attrs = component.getAttributes(); > > writer.writeAttribute("for", component.getClientId(context), > > null); > > > > UIInput input = > > (UIInput)component.findComponent((String)attrs.get("for")); > > if(input.isRequired()) > > writer.write("*"); > > > > writer.write(attrs.get("value").toString()); > > } > > > > public void encodeEnd(FacesContext context, UIComponent > component) > > throws java.io.IOException { > > ResponseWriter writer = context.getResponseWriter(); > > writer.endElement("label"); > > } > > } > > > > What's cool about this is that all h:outputLabel tags will be fitted > > with our custom renderer, so by modifying the config file and > > implementing the renderer, we are changing the behavior of existing > > JSP pages without modifying the pages themselves. All labels that > > decorate required fields will be prepended with asteriks. > > > > Notice that my simple renderer is not industrial strength. > It does not > > account for all the h:outputLabel attributes, nor does it allow a > > nested component. But it's not too bad for 20 minutes of work. > > > > btw, it's easy to add an enhancement so that the asterik is > red if the > > corresponding field failed validation. Here's the modified > encodeBegin > > method of the renderer: > > > > ... > > public void encodeBegin(FacesContext context, UIComponent component) > > throws java.io.IOException { > > ResponseWriter writer = context.getResponseWriter(); > > writer.startElement("label", component); > > > > String styleClass = (String) > > component.getAttributes().get("styleClass"); > > if (styleClass != null) > > writer.writeAttribute("class", styleClass, null); > > > > Map attrs = component.getAttributes(); > > writer.writeAttribute("for", component.getClientId(context), > > null); > > > > UIInput input = > > (UIInput)component.findComponent((String)attrs.get("for")); > > if(input.isRequired()) { > > boolean msgs = hasMessages(context, input); > > if(msgs) { > > writer.startElement("font", null); > > writer.writeAttribute("color", "red", null); > > } > > writer.write("*"); > > if(msgs) { > > writer.endElement("font"); > > } > > } > > writer.write(attrs.get("value").toString()); > > } > > > > private boolean hasMessages(FacesContext context, UIComponent > > component) { > > Iterator it = context.getClientIdsWithMessages(); > > boolean found = false; > > > > while(it.hasNext()) { > > String id = (String)it.next(); > > if(component.getClientId(context).equals(id)) > > found = true; > > } > > return found; > > } > > ... > > > > david > > > >> > >>> > >>> Thanks, > >>> > >>> Matt > >>> > >>>> > >>>>> Do I have to subclass the existing JSP Tag to do this? > >>>> > >>>> > >>>> You hardly ever want to subclass an existing component > tag, because > >>>> tags are really just thin veneers for component/renderer > pairs. You > >>>> could, however, implement your own Label renderer and > plug it into > >>>> h:outputLabel. But I would opt for one of the easier solutions > >>>> above. > >>>> > >>>>> 2. Is it possible to auto-add a colon? I'm able to do > this pretty > >>>>> easily with a custom taglib and Commons Validator, but it seems > >>>>> difficult with MyFaces? With Tapestry, I can subclass the > >>>>> existing component and add my own suffix (including a > space before > >>>>> the colon for the French locale). > >>>> > >>>> > >>>> The same techniques for prepending an asterik will work for > >>>> appending a colon. Again, you could implement your own Label > >>>> renderer that does anything you want. > >>>> > >>>> > >>>> david > >>>> > >>>>> > >>>>> Thanks, > >>>>> > >>>>> Matt > >>>>> > >>>> > >>> > >> > > > >

