Sometimes what you need is just a hair’s breath away. For example you are trying to implement a css theme down to the tiniest detail and you have to fight with what XPages normally outputs in some cases: in this very specific one I needed to give more padding to an input control when displayed as readonly
.
While trying to avoid going all the way down to rewriting the renderers and/or alternating them whenever a control is displayed as read-only or not I made a small discovery: there are some useful handles for the pre-existing ReadOnlyRenderer
that can be leveraged by means of an XPages theme. Have a look at the renderer source code:
/* */ public class ReadOnlyRenderer
/* */ extends Renderer
/* */ {
/* */ public ReadOnlyRenderer() {}
/* */
/* */ protected String getReadOnlyStyle(FacesContext paramFacesContext, UIComponent paramUIComponent)
/* */ {
/* 31 */ return (String)paramUIComponent.getAttributes().get("readOnlyStyle");
/* */ }
/* */
/* */ protected String getReadOnlyStyleClass(FacesContext paramFacesContext, UIComponent paramUIComponent)
/* */ {
/* 36 */ return (String)paramUIComponent.getAttributes().get("readOnlyStyleClass");
/* */ }
/* */ }
The renderer consists of two methods that are looking for two specific properties: readOnlyStyle
and readOnlyStyleClass
. Those properties can’t be defined at the input control level, they are simply not there and you can’t type them manually from the XPage because you know that any undefined property will make the compiler fail. But that doesn’t mean you can’t “smuggle” them in right from the back door – read theme definition. Sooo…
<control>
<name>InputField</name>
<property mode="concat">
<name>styleClass</name>
<value>form-control</value>
</property>
<property>
<name>readOnlyStyleClass</name>
<value>form-control-static</value>
</property>
</control>
There you go!
But there is more. You might have noticed in the source code that there’s a p
tag instead of the classic span
tag that is generally printed. It turns out that there can be as many readonly
renderers as there are inputs. All I did therefore was to customized the pre-existing renderer to output the tag I wanted and later list it in the faces-config.xml
.
package demo;
import com.ibm.xsp.renderkit.html_basic.ReadOnlyValueRenderer;
public class UIReadOnlyValueRenderer extends ReadOnlyValueRenderer {
@Override
protected String getElement() {
return "p";
}
}
<renderer>
<component-family>javax.faces.Input</component-family>
<renderer-type>javax.faces.Text.ReadOnly</renderer-type>
<renderer-class>demo.UIReadOnlyValueRenderer</renderer-class>
</renderer>
Done!