Define tags, abstract tag superclasses, or other named reference-able definitions. These are elements which contain other elements. Includes the -extension elements which allow any contents.
A composite-component
is a component
which will load the contents of a Custom Control page as its children.
To create a Custom Control, use the Domino Designer editor. You can use the Property Definition tab of the Custom Control editor to add properties that may be set in the outer page. To see the xsp-config file generated by the Custom Control editor, open the Navigator view; in the menus Window, Show Eclipse Views, Other..., General, Navigator. Then browse to your application, open the CustomControls folder and you'll see the .xsp file and .xsp-config file corresponding to your custom control. If you open the xsp-config file, you'll see the composite-component definition for the custom control.
For example, you might have a custom control "recipeCustom", with this contents in the recipeCustom.xsp-config:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
<faces-config-extension>
<namespace-uri>http://www.ibm.com/xsp/custom</namespace-uri>
<default-prefix>xc</default-prefix>
</faces-config-extension>
<composite-component>
<component-type>recipeCustom</component-type>
<composite-name>recipeCustom</composite-name>
<composite-file>/recipeCustom.xsp</composite-file>
<property>
<property-name>recipeName</property-name>
<property-class>string</property-class>
</property>
<property-type>
<property-name>ingredient</property-name>
<property>
<property-name>name</property-name>
<property-class>string</property-class>
</property>
<property>
<property-name>quantity</property-name>
<property-class>int</property-class>
</property>
<property-extension>
<collection-property>true</collection-property>
</property-extension>
</property-type>
</composite-component>
</faces-config>
The recipeCustom.xsp file displaying the property value and the list of property-type values might be like so (XPage snippet):
A test XPage using that control would be like so:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xc:recipeCustom id="applePie" recipeName="Apple Pie">
<xc:this.ingredient>
<xc:ingredient name="egg" quantity="1"></xc:ingredient>
<xc:ingredient name="apples" quantity="4"></xc:ingredient>
<xc:ingredient name="flour (in tbls)" quantity="6"></xc:ingredient>
</xc:this.ingredient>
</xc:recipeCustom>
<xp:br></xp:br>
</xp:view>
The page corresponding to the composite-file
is included into the outer page at the location of the composite-component
tag. The composite-file
page can reference the properties of the composite-component
using the "compositeData" global variable.
If you are copying a Custom Control to an XPages Extension Library, then composite-file can correspond to the class of a compiled Custom Control, like so:
<composite-file>/com/example/component/recipe/recipeCustom</composite-file>
The composite-component
s also differ from normal component
s in that they can define property-type
s, so it is not necessary to define a complex-type
for custom tags within a composite-component's <this.propertyName/> tags. The xc:ingredient tag in the sample above is a property-type tag.
Present in composite-component
s and property-type
s.
To create property-type definitions, you would create a Custom Control in Designer, and in the Property Definition tab, click the New Group button. Those Property Definition groups are represented in the xsp-config files by property-type definitions. They are not to be confused with xsp-config group definitions, which are different.
The property-type
s act like complex-type
s in that they define a tag which can have property
s and can appear within a <this.propertyName/> tag on a page. The differences are that complex-type
s must have a corresponding Java class, while property-types do not, and complex-types can be used in any property that allows a value with that Java class, while property-type tags are restricted to appearing in a single property, the property where the property-type tag was defined.
The property-type
does not indicate a Java class because it is represented at runtime by a map. The names of the contained property
s are keys which map to the property values.
A property-type
tag cannot appear at any location in a page. A property-type
's complex tag can only appear within the same property-type
's this.propertyName tag.
A property-type can be declared as allowing multiple property-type definition tags within the this.propertyName tags, by including a collection-property within the property-extension.
For example, for a collection-property
property-type
named "ingredient", the eg:ingredient
tag will only be valid within the eg:this.ingredient
tag, and it is the only tag allowable there. (XPage snippet)
<eg:this.ingredient>
<eg:ingredient name="eggs" quantity="1"/>
<eg:ingredient name="apples" quantity="4"/>
</eg:this.ingredient>
A property-type
's property-name
must be unique to its container composite-component
or property-type
. It must not conflict with the container's other property-type
's names, nor with the property
or attribute
names.
At runtime, a composite-component
's property-type
values can be referenced from value bindings in the composite-file
in the same way that the property
s values can be used.
In the example above in the composite-component
section, the ingredient property-type is defined by:
<property-type>
<property-name>ingredient</property-name>
<property>
<property-name>name</property-name>
<property-class>string</property-class>
</property>
<property>
<property-name>quantity</property-name>
<property-class>int</property-class>
</property>
<property-extension>
<collection-property>true</collection-property>
</property-extension>
</property-type>
That property-type defines both the property-type definition tag, and also the property-type this.ingredient property to be used on the custom control tag. The collection-property extension is configures the this.ingredient property as allowing multiple values, while the nested property elements define the property names allowed on the ingredient tag definition.
A group of property
s. A group definition is referenced by group-type-ref
s in component
s and other definitions. So extracting properties to a group instead of defining them in-line within the definition element means that the same property elements can be reused in multiple definition elements.
The other mechanism for reusing properties is through inheritance, but that has limitations as a definition can only define a single parent. (See definition inheritence trees).
A group can in turn contain other groups, but it is recommended not to have more than 2 containment levels, as it becomes confusing.
The convention is to usually have collection groups containing multiple properties, with no contained inner groups. Some collection groups represent the properties available on a a Java interface, for example, the group with group-type javax.faces.component.group.ActionSource is named after the Java interface javax.faces.component.ActionSource. It appears as:
<group>
<!-- The group of properties for the interface javax.faces.component.ActionSource -->
<group-type>javax.faces.component.group.ActionSource</group-type>
<property>
<description>MethodBinding representing the application action ...</description>
<display-name>Application Action</display-name>
<property-name>action</property-name>
<property-class>javax.faces.el.MethodBinding</property-class>
<property-extension>
<!-- public String <actionMethodName>(); -->
<method-binding-property>true</method-binding-property>
<method-return-type>java.lang.String</method-return-type>
<designer-extension>
<category>events</category>
</designer-extension>
</property-extension>
</property>
<!-- ... also <property-name>actionListener</property-name> -->
<!-- ... also <property-name>actionListeners</property-name> -->
<!-- ... also <property-name>immediate</property-name> -->
</group>
which is referenced by the definition for UICommand, an ancestor of the Button and Event Handler controls:
<component>
<component-type>javax.faces.Command</component-type>
<component-class>javax.faces.component.UICommand</component-class>
<group-type-ref>javax.faces.component.group.ActionSource</group-type-ref>
<property>
<description>
Specifies the value of the control. Value is typically rendered as a label.
</description>
<display-name>Value</display-name>
<property-name>value</property-name>
<property-class>java.lang.Object</property-class>
<property-extension>
<localizable>true</localizable>
<designer-extension>
<category>basics</category>
</designer-extension>
</property-extension>
</property>
<component-extension>
<base-component-type>javax.faces.Component</base-component-type>
<component-family>javax.faces.Command</component-family>
<renderer-type>javax.faces.Button</renderer-type>
</component-extension>
</component>
Other groups represent related HTML attributes, like the ...core group (containing the properties style, styleClass and title), or the ...i18n internationalization group (lang and dir)
However, there are some reasons for using groups within groups; you may sometimes need to copy and modify one of the properties in a group. In that case, the recommendation is to use a group-of-groups and multiple single-property groups. (To reuse an existing translated label, use the label reference mechanism) For example, the ValueHolder "value" property is usually not localizable, but for the Label control it was necessary to mark the property as translatable. In that case, the solution was to extract each of the properties in the group out to its own single-property group, and change the original group to a container referencing the single-property groups. The localizable single-property group was copied, the group-type was changed, and the localizable extension was set to true. Now the UIOutput superclass definition refers to the main group, but the Label control definition overrides the superclass "value" property by referring to the localizable value single-property group.
Example showing the ValueHolder value property and the localizable ValueHolder value property.
<group>
<!-- one of the properties in the interface javax.faces.component.ValueHolder -->
<group-type>javax.faces.component.group.ValueHolder.prop.value</group-type>
<property>
<description>Contains the current value of the control</description>
<display-name>Value</display-name>
<property-name>value</property-name>
<property-class>java.lang.Object</property-class>
<property-extension>
<designer-extension>
<category>data</category>
</designer-extension>
</property-extension>
</property>
</group>
<group>
<!-- one of the properties in the interface javax.faces.component.ValueHolder -->
<group-type>javax.faces.component.group.ValueHolder.prop.converter</group-type>
<property>
<description>Converter instance registered with this control</description>
<display-name>Converter</display-name>
<property-name>converter</property-name>
<property-class>javax.faces.convert.Converter</property-class>
<property-extension>
<designer-extension>
<category>data</category>
</designer-extension>
</property-extension>
</property>
</group>
<group>
<!-- The group of properties for the interface javax.faces.component.ValueHolder -->
<group-type>javax.faces.component.group.ValueHolder</group-type>
<group-type-ref>javax.faces.component.group.ValueHolder.prop.value</group-type-ref>
<group-type-ref>javax.faces.component.group.ValueHolder.prop.converter</group-type-ref>
</group>
<component>
<component-type>javax.faces.Output</component-type>
<component-class>javax.faces.component.UIOutput</component-class>
<group-type-ref>javax.faces.component.group.ValueHolder</group-type-ref>
<component-extension>
<base-component-type>javax.faces.Component</base-component-type>
<component-family>javax.faces.Output</component-family>
<renderer-type>javax.faces.Text</renderer-type>
</component-extension>
</component>
<group>
<!-- Override the ValueHolder value property with a localizable one -->
<group-type>javax.faces.component.group.ValueHolder.prop.value.localizable</group-type>
<property>
<description>Contains the current value of the control</description>
<display-name>Value</display-name>
<property-name>value</property-name>
<property-class>java.lang.Object</property-class>
<property-extension>
<localizable>true</localizable>
<designer-extension>
<category>data</category>
</designer-extension>
</property-extension>
</property>
</group>
<component>
<description>A control that displays text</description>
<display-name>Label</display-name>
<component-type>com.ibm.xsp.OutputLabel</component-type>
<component-class>com.ibm.xsp.component.xp.XspOutputLabel</component-class>
<group-type-ref>javax.faces.component.group.ValueHolder.prop.value.localizable</group-type-ref>
<!-- ... other group-type-refss and properties -->
<component-extension>
<base-component-type>com.ibm.xsp.UIOutputEx</base-component-type>
<renderer-type>com.ibm.xsp.OutputLabel</renderer-type>
<tag-name>label</tag-name>
<designer-extension>
<category>core</category>
</designer-extension>
</component-extension>
</component>
You may want to reuse these groups:
<group-type-ref>com.ibm.xsp.group.FacesDojoComponent.prop.dojoAttributes</group-type-ref>
<group-type-ref>com.ibm.xsp.group.FacesDojoComponent.prop.dojoType</group-type-ref>
<group-type-ref>com.ibm.xsp.group.FacesDojoComponent</group-type-ref>
<group-type-ref>
com.ibm.xsp.group.FacesInputComponent.prop.disableClientSideValidation
</group-type-ref>
<group-type-ref>com.ibm.xsp.group.FacesInputComponent.prop.disableModifiedFlag</group-type-ref>
<group-type-ref>com.ibm.xsp.group.FacesInputComponent.prop.disableValidators</group-type-ref>
<group-type-ref>com.ibm.xsp.group.FacesInputComponent</group-type-ref>
<group-type-ref>com.ibm.xsp.group.aria.role</group-type-ref>
<group-type-ref>com.ibm.xsp.group.core.prop.style</group-type-ref>
<group-type-ref>com.ibm.xsp.group.core.prop.styleClass</group-type-ref>
<group-type-ref>com.ibm.xsp.group.core.prop.title</group-type-ref>
<group-type-ref>com.ibm.xsp.group.core</group-type-ref>
<group-type-ref>com.ibm.xsp.group.events.onkey</group-type-ref>
<!-- .events.onkey has properties onkeypress, onkeydown, onkeyup -->
<group-type-ref>com.ibm.xsp.group.events.onmouse</group-type-ref>
<!-- .events.onmouse has properties onmousedown, onmouseup,
onmouseover, onmousemove, onmouseout -->
<group-type-ref>com.ibm.xsp.group.events.prop.onclick</group-type-ref>
<group-type-ref>com.ibm.xsp.group.events.prop.ondblclick</group-type-ref>
<group-type-ref>com.ibm.xsp.group.events</group-type-ref>
<group-type-ref>com.ibm.xsp.group.filter.prop.htmlFilter</group-type-ref>
<group-type-ref>com.ibm.xsp.group.filter.prop.htmlFilterIn</group-type-ref>
<group-type-ref>com.ibm.xsp.group.filter</group-type-ref>
<!-- the .filter group corresponds to the
FacesInputFiltering and FacesOutputFiltering interfaces -->
<group-type-ref>com.ibm.xsp.group.focus.prop.accesskey</group-type-ref>
<group-type-ref>com.ibm.xsp.group.focus.prop.onblur</group-type-ref>
<group-type-ref>com.ibm.xsp.group.focus.prop.onfocus</group-type-ref>
<group-type-ref>com.ibm.xsp.group.focus.prop.tabindex</group-type-ref>
<group-type-ref>com.ibm.xsp.group.focus</group-type-ref>
<group-type-ref>com.ibm.xsp.group.i18n.prop.dir</group-type-ref>
<group-type-ref>com.ibm.xsp.group.i18n.prop.lang</group-type-ref>
<group-type-ref>com.ibm.xsp.group.i18n</group-type-ref>
<group-type-ref>com.ibm.xsp.group.input.prop.disabled</group-type-ref>
<group-type-ref>com.ibm.xsp.group.input.prop.onchange</group-type-ref>
<group-type-ref>com.ibm.xsp.group.input.prop.onselect</group-type-ref>
<group-type-ref>com.ibm.xsp.group.input.prop.readonly</group-type-ref>
<group-type-ref>com.ibm.xsp.group.input</group-type-ref>
<group-type-ref>com.ibm.xsp.group.outerStyleClass</group-type-ref>
<group-type-ref>javax.faces.component.group.ActionSource</group-type-ref>
<!-- .ActionSource has properties action, actionListener, actionListeners, immediate,
but generally you would extend a UICommand component to inherit those properties. -->
<group-type-ref>javax.faces.component.group.EditableValueHolder</group-type-ref>
<!-- .EditableValueHolder has properties
required, validator, validators, valueChangeListener, valueChangeListeners, immediate
but generally you would extend a UIInput component to inherit those properties. -->
<group-type-ref>javax.faces.component.group.ValueHolder.prop.converter</group-type-ref>
<group-type-ref>javax.faces.component.group.ValueHolder.prop.value.localizable</group-type-ref>
<group-type-ref>javax.faces.component.group.ValueHolder.prop.value</group-type-ref>
<group-type-ref>javax.faces.component.group.ValueHolder</group-type-ref>
<!-- .ValueHolder has properties converter, value
but generally you would extend a UIOutput component to inherit those properties. -->
<!-- The following are groups used in complex-type definitions. -->
<group-type-ref>com.ibm.xsp.model.group.DataSource</group-type-ref>
<!-- .DataSource has properties scope, ignoreRequestParams, requestParamPrefix, var-->
<group-type-ref>com.ibm.xsp.resource.group.Resource</group-type-ref>
<!-- .Resource has the property rendered -->
<group-type-ref>com.ibm.xsp.validator.group.Validator</group-type-ref>
<!-- .Validator has the property message -->
A render-kit definition in an xsp-config file enables the use of render-kit tags for that render-kit. For example, if we define a xsp-config render-kit for the render-kit-id "HTML_RCP", then that implicitly creates an xp:componentTagName.HTML_RCP tag for every component tag that is currently defined.
So this definition:
<faces-config>
<faces-config-extension>
<namespace-uri>http://www.ibm.com/xsp/core</namespace-uri>
<default-prefix>xp</default-prefix>
</faces-config-extension>
<render-kit>
<display-name>Rich Client Platform</display-name>
<render-kit-id>HTML_RCP</render-kit-id>
<render-kit-extension>
<render-kit-alias>rcp</render-kit-alias>
<base-render-kit-id>HTML_BASIC</base-render-kit-id>
</render-kit-extension>
</render-kit>
</faces-config>
would allow the use of these render-kit tags in an XPage (XPage snippet):
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:label value="Enter value: " id="label1">
<xp:label.HTML_RCP value="Enter plain text value: "/>
</xp:label>
<xp:inputText id="inputText1" value="#{sessionScope.value}">
<xp:inputText.HTML_RCP style="width:80%" />
</xp:inputText>
<xp:br></xp:br>
<xp:button value="Submit" id="button1">
<xp:button.HTML_RCP value="Save"/>
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete" immediate="false" save="true"></xp:eventHandler>
</xp:button>
</xp:view>
Those render kit tags may contain any property defined on the control tag.
At runtime, the active render-kit will be one of the render-kits defined in the runtime faces-config.xml files. In XPages, the kit "HTML_BASIC" is used on the web, while the kit "HTML_RCP" is used in the Notes client (RCP is Rich Client Platform). When the active kit is HTML_RCP, then in the XPage above, the property values from the render-kit tag will be used as well as the values from the main control tag. Where there is a conflict, with properties being defined both on the main tag and on the render-kit tag, then the HTML_RCP render-kit tag values will be used. Overall, this means that the HTML_RCP render-kit tags can be used to set property values that will only apply in the Notes Client.
The opposite does not apply; you cannot use the HTML_BASIC render-kit tags to set values that only appear on the web. That is because the HTML_RCP render-kit declares that it extends from the base HTML_BASIC render-kit, because controls that appear in the Rich Client are based on the web controls (actually in most cases the exact same output is used).
In fact it is possible to define a tree of render-kits, though it is not recommended. If you had a tree like so:
- HTML_BASIC
- HTML_RCP
- HTML_SAMETIME
- HTML_NOTES
- HTML_MOBILE
Then when the active render-kit at runtime is HTML_NOTES, then the values would be used from tags named: xp:button.HTML_NOTES, xp:button.HTML_RCP, xp:button.HTML_BASIC, but values would not be used from tags named xp:button.HTML_MOBILE nor xp:button.HTML_SAMETIME.
Another way to achieve the same effect is to define property values programmatically using the expression: context.isRunningContext('Notes') which will indicate if the XPage is running in the Notes client. For example (XPage snippet):
<xp:label id="label1">
<xp:this.value><![CDATA[#{javascript:
if( context.isRunningContext('Notes') ){
return "Enter plain text value: ";
}
return "Enter value: ";
}]]></xp:this.value>
</xp:label>
Using an alias
The render-kit-alias ("rcp") in the xsp-config example above provides another set of tags that may be used, in the form xp:componentTagName.rcp. Multiple aliases can be defined for a single render-kit. At present the HTML_RCP render-kit has the alias "rcp", and the HTML_BASIC render-kit has the alias "html". The alias names are case sensitive. So the xp:label.HTML_RCP tag above becomes (XPage snippet):
<xp:label value="Enter value: " id="label1">
<xp:label.rcp value="Enter plain text value: "/>
</xp:label>
Renderer property sets
If your components have been defined with a component-family and a renderer-type, then it is possible to define extra sets of properties that may be used on the render-kit tags, besides the default set of properties that are defined on the component tag.
For example, if you know that the Button control is defined with the component-extension containing the component-family "com.ibm.xsp.ButtonEx" and the renderer-type "com.ibm.xsp.ButtonEx", then it is possible to define an extra property named "something" like so:
<faces-config>
<faces-config-extension>
<namespace-uri>http://example.com</namespace-uri>
<default-prefix>eg</default-prefix>
</faces-config-extension>
<render-kit>
<render-kit-id>HTML_RCP</render-kit-id>
<renderer>
<component-family>com.ibm.xsp.Command</component-family>
<renderer-type>com.ibm.xsp.ButtonEx</renderer-type>
<renderer-class>com.sun.faces.renderkit.html_basic.ButtonRenderer</renderer-class>
<attribute>
<attribute-name>something</attribute-name>
<attribute-class>java.lang.String</attribute-class>
</attribute>
</renderer>
</render-kit>
</faces-config>
If the control component-extension does not define a component-family and renderer-type then it will not be possible to add renderer property sets to the render-kit tags.
In that renderer element, the component-family, renderer-type and renderer-class are required, even though the renderer-class from an xsp-config file is never used. If the render-kit-id is absent, then the renderer property set is contributed to the HTML_BASIC render-kit. At design-time the control's component-family and renderer-type are used to look up which renderer definition defines the renderer property set for the render-kit tag's render-kit. With that xsp-config file in place, it will then be possible to use the "something" property on the xp:button.rcp tag, like so (XPage snippet):
At runtime, the "something" value will be present in the server-side button object, but by default it will not appear in the HTML output for the XPage. The value can be accessed programmatically using getAttributes().get('something') To make the value appear in the HTML output of the page, it would be necessary to provide a different runtime renderer for the control, so that instead of the standard XPages mechanism for outputting the button control as HTML in the XPage, you would override that default rendering with your own renderer, to output any HTML you want in places where the button tag is used. Your new runtime renderer might then get the "something" value programmatically and output it to the HTML page.
Lower level elements generally only contain text. These are used within the other elements above.
.
No expected content. The <description>, <display-name>, <icon> from the render-kit element are parsed but not used anywhere (the display-name was used in 8.5.0 but is not needed).