+1 also.
Matt Cooper wrote:
> +1 on supporting an iterator around form items, I feel that would be
> quite a powerful enhancement
>
> On 6/5/07, *Adam Winer* < [EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>>
> wrote:
>
> On 6/4/07, * Matt Cooper* <[EMAIL PROTECTED]
> <mailto:[EMAIL PROTECTED]>> wrote:
>
> I think decoupling of these renderers would be a good thing.
> The trick will be to make sure the form item renders properly
> when it is a direct child of the form layout component. Let's
> say that you put a tr:panelGroupLayout (or some other non form
> layout component) inbetween the form layout component and the
> form item--I feel that that particular form item should render
> the same as if there was no form layout involved (this would
> be insulating the form item from the form layout).
>
>
> One of the big questions to decide when decoupling is whether you
> want the parent component to augment/enhance the rendering of the
> children or for the child to be passed more information to render
> itself differently. In this case, I wonder if both might be
> desirable, and I could imagine:
> - A generic mechanism whereby a parent renderer could say "on my
> children, here's a CoreRendererDecorator that I'd like to have
> called for any child CoreRenderer", akin to a servlet fil
> - A generic mechanism whereby a parent could publish rendering
> information and child could ask for it, decoupled from looking at
> the renderer and component (so we don't have getParent() or
> getParent().getRenderer() and "instanceof" calls), something like
> Object RenderingContext.getDescriptor(UIComponent parent)? This'd
> let us have classes like FormLayoutData in the public API,
> decoupling the renderers, without forcing us to move the renderers
> themselves into the public API.
>
>
> When considering a decoupling approach, you will also want
> consider cases where a developer wants to have one kind of a
> form layout component inside of another form layout
> component. There will need to be some sort of mechanism to
> ensure the correct rendering path is taken for the each
> particular component hierarchy so a simple "am I contained, at
> any level, in a form layout" might not be sufficient but an
> "am I a direct child of a form layout" might.
>
> Today, I believe if you have a tr:panelFormLayout inside of
> another tr:panelFormLayout, the outer layout will have labels
> on the side of the contents and the inner layout will have the
> labels above the contents. This is determined by a request
> attribute that is present only during the encodeAll of the
> PanelFormLayout's encoding.
>
> One final tip... There is one particular case where a form
> item isn't a direct child of the form layout but will still
> render as a form item: when it is contained in a tr:group
> component and that tr:group is a direct child of the form
> layout. The tr:group component is used by the form layout
> renderer to draw separator lines between groups of form items.
>
>
> And, in addition, I think a lot of people really wish that if you
> had a tr:iterator inside of
> a tr:panelFormLayout, that children of that iterator would render
> as a form item. I think
> a CoreRendererDecorator approach might accomplish that...
>
> -- Adam
>
>
>
> Regards,
> Matt
>
>
> On 5/24/07, *Leonardo Uribe* <[EMAIL PROTECTED]
> <mailto:[EMAIL PROTECTED]>> wrote:
>
> Hi everybody.
>
> I'm working on a trinidad component for do layout (as part
> of a Google Summer of Code) more easy and with less code
> than panelFormLayout component.
>
> Checking the code, I found a strong coupling between the
> classes PanelFormLayoutRenderer and LabelAndMessageRenderer.
>
> I found the following points:
>
> 1. LabelAndMessageRenderer has about 3 behaviors,
> depending what is his parent components. In the code it
> checks in a method something like
> that:
>
> private boolean _isFormRendererType(String rendererType)
> {
> return
> "org.apache.myfaces.trinidad.Form".equals(rendererType) ||
>
> "org.apache.myfaces.trinidad.FormLayout
".equals(rendererType)
> ||
> "org.apache.myfaces.trinidad.rich.Form
> ".equals(rendererType) ;
> }
>
> Because my component is a new component, i have to add a
> line like this
>
> return
> "org.apache.myfaces.trinidad.Form".equals(rendererType) ||
> "org.apache.myfaces.trinidad.FormLayout
> ".equals(rendererType) ||
>
> "org.apache.myfaces.trinidad.rich.Form".equals(rendererType)
> ||
> "org.apache.myfaces.
> trinidad.TableLayout".equals(rendererType);
>
> But this is very hacky. I have to do this because i need
> that the method in encodeAll of LabelAndMessageRenderer
>
> boolean needsPanelFormLayout =
_isParentPanelForm(component);
>
> returns true, because my component layout a table like
> panelFormLayout.
>
> 2. In other part of the code, LabelAndMessageRenderer call
> this method (in encodeAll)
>
> if (needsPanelFormLayout)
> {
>
> if(PanelFormLayoutRenderer.encodeBetweenLabelAndFieldCells
(context,
> arc, rw))
> {
> renderRootDomElementStyles(context, arc,
> component, bean);
> }
> }
>
> What if my component has another behavior to this method?
> PanelFormLayoutRenderer detects if this panelFormLayout is
> inside
> another panelFormLayout and because if it is the case, it
> adds between Label and Field Cells something like this
>
> rw.endElement("tr"); // label row
> rw.startElement("tr", null); // field row
>
> So, the label is rendered on top of the field.
>
> 3. LabelAndMessageRenderer do this for render a Label an a
> field (please look the parts in yellow)
>
> private void _renderLabelCell(
> FacesContext context,
> RenderingContext arc,
> UIComponent component,
> FacesBean bean,
> boolean labelExists) throws IOException
> {
> ResponseWriter rw = context.getResponseWriter();
> rw.startElement("td", null);
>
> // render labelStyleClass and defaultStyleClass.
> renderStyleClasses(context, arc, new String[]{
> getLabelStyleClass(bean),
> _getDefaultLabelStyleClass(arc,
>
> SkinSelectors.AF_LABEL_TEXT_STYLE_CLASS )});
>
> String labelInlineStyle = getLabelInlineStyleKey(bean);
> rw.writeAttribute("style", labelInlineStyle, null);
>
> String valign = getDefaultLabelValign(bean);
>
> rw.writeAttribute ("valign", valign, null);
> if (isDesktop(arc))
> rw.writeAttribute("nowrap", Boolean.TRUE, null);
>
> if (labelExists)
> {
> rw.writeAttribute("width",
>
> arc.getProperties().get(_LABEL_CELL_WIDTH_KEY),
> null);
> }
>
> delegateRenderer(context, arc, component, bean, _label);
> rw.endElement ("td");
> }
>
> private void _renderFieldCell(
> FacesContext context,
> RenderingContext arc,
> UIComponent component,
> FacesBean bean,
> boolean labelExists,
> boolean needsPanelFormLayout,
> boolean isInline) throws IOException
> {
> ResponseWriter rw = context.getResponseWriter();
> rw.startElement("td", null);
>
> rw.writeAttribute("valign", "top", null);
> rw.writeAttribute("nowrap", Boolean.TRUE, null);
>
> renderStyleClass(context, arc,
> SkinSelectors.AF_CONTENT_CELL_STYLE_CLASS );
>
> if (labelExists)
> rw.writeAttribute("width",
>
> arc.getProperties().get(_FIELD_CELL_WIDTH_KEY),
> null);
>
> renderFieldCellContents(context, arc, component, bean);
>
> // The panelForm places messages below the fields, not
> on a separate
> // row:
> if (needsPanelFormLayout)
> {
> // =-= mcc PPR PROBLEM!!! We should always be
> rendering the "div",
> // and always rendering an ID, if we ever want
> it to be PPR
> // replaceable:
> if (isInline || hasMessage(context, arc, component,
> bean))
> {
> rw.startElement("div", null);
> renderStyleClass(context, arc,
>
> SkinSelectors.AF_COMPONENT_MESSAGE_CELL_STYLE_CLASS);
> _renderMessageCellContents(context, arc,
> component, bean);
> rw.endElement("div");
> }
> }
>
> // bug 2484841: PDA: TOO MUCH WHITESPACE BETWEEN
> // INPUT ELEMENTS IN LABELEDFIELD
> // This is a browser bug workaround, hopefully we can
> remove it eventually
> if (isPDA(arc) && isIE(arc))
> {
> rw.startElement("div", null);
> renderSpacer(context, arc, "1", "0");
> rw.endElement("div");
> }
>
> rw.endElement("td");
> }
>
> I need to add an attribute in the td tag like <td
> colspan=2 rowspan=3 height=XXX width=XXX .........>, but
> if i want this, i need to
> modify LabelAndMessageRenderer to recognize if the parent
> component is my component, check if it has an attribute
> like this
>
> <mycomp:tableFormLayout
> labelWidth="100" width="400" height="300"
> fieldWidth="100" rows="100"
> columns="1*;1*;1*" >
> <tr:selectOneChoice
> label="Salutation">
> <f:selectItem itemLabel="1
> Option" itemValue="1" />
> <f:attribute name="spanXItem"
> value="2"/>
> <f:attribute name="spanYItem"
> value="3"/>
> </tr:selectOneChoice>
> </mycomp:tableFormLayout>
>
> and finally add a colspan or rowspan (height and width are
> optional).
>
> ---------
> Conclusion?: It's necesary to decouple
> PanelFormLayoutRenderer and other FormRenderers with
> LabelAndMessageRenderer in order to avoid
> those hacks. I propose to create an interface that
> implements some affected methods or create new ones, and
> delegate this rendering to the parent
> classes.
>
> I want to you what should be better to do in that case. If
> its necesary to refactor the classes, how it can be done.
>
> Thanks for your attention
>
> regards
>
> Att: Leonardo Uribe
> Ingeniero de Sistemas
> Pontificia Universidad Javeriana
> Ingeniero Electronico
> Universidad Nacional de Colombia
>
>
>
>
>
>
>
>
>
>