XPages Tip: Adding a Bootstrap Class to All Labels via the Theme

Datetime:2016-08-22 22:22:03          Topic: Bootstrap           Share

In this post, I showed how to set all labels in an application to include a class to pick up Bootstrap styling so it could be applied application-wide and not require touching every label control individually. However, there’s a quirk with label rendering that may make it not apply universally as desired. In this post, I’ll explain the issue and how to use another theme setting to easily fix it.

Updating all Labels via the Theme

This code in the theme will apply the control-label class to all label components in the application. This allows me to apply a Bootstrap style class to all labels without having to update each label control individually on every XPage and custom control.

<control>
  <name>Text.Label</name>
  <property mode="concat">
    <name>styleClass</name>
    <value>control-label</value>
  </property>
</control>

The Bootstrap styling will be applied to label tags that have the control-label class.

The Problem with Label Rendering

However, there’s an issue with the way labels are rendered that may not make it work consistently.

Any labels that do not have a for attribute specified will actually be rendered as span tags and the styling will not be picked up. (Labels that have the for attribute specified will be rendered as label tags and work as expected.)

In another post, I described the effects of different modes on theme property application . In this post, we’ll see a practical example of the effects.

Theme to the Rescue (Again)

Fortunately, there’s an easy way to add another property setting to the theme to handle this.

There isn’t a tagName attribute on a label, so you can’t directly modify the output tag this way, but for is a property of the control, so you can use the theme to add it to all labels.

1. Overriding the Property

One option is to override the for property on all labels. Lines 7-10 were added below to do so.

<control>
  <name>Text.Label</name>
  <property mode="concat">
    <name>styleClass</name>
    <value>control-label</value>
  </property>
  <property mode="override">
    <name>for</name>
    <value>dummyTarget</value>
  </property>	
</control>

This puts the for property in place and assumes it needs to figure out the client-side ID of the element that’s been specified. This is a dummy value, but it does the job.

<label id="view:_id1:_id3:_id51:office_Label1" class="control-label" for="view:_id1:_id3:_id51:dummyTarget">Office</label>

However, it does the job too ambitiously. It removes any existing for property, so it would break the association with the specified input control, which may cause other issues with the application and most certainly would cause issues with a screen reader.

2. Concatenating the Value

Changing line 7 to concatenate instead of overriding the value gives us a bit better behavior.

<property mode="concat">

This mode will append the property value to any value that currently exists for the attribute. It will also add the attribute and value if it doesn’t exist.

<label id="view:_id1:_id3:_id51:label17" class="control-label" for="view:_id1:_id3:_id51:dummyTarget">Payment #</label>

This also does the job, but it causes two values to be in the for property if one already existed (although it doesn’t try to generate a client-side ID when it’s appended).

<label id="view:_id1:_id3:_id51:office_Label1" class="control-label" for="view:_id1:_id3:_id51:office1 dummyTarget">Office</label>

This is better than the override method, but still may cause problems.

3. Mode not specified

You can also just not specify the mode.

<property>

In this case it only adds the property and value if the property doesn’t already exist, so it’s the cleanest solution.

This is an example of a label that already had the for attribute specified. It does not get the new dummy value.

<label id="view:_id1:_id3:_id51:office_Label1" class="control-label" for="view:_id1:_id3:_id51:office1">Office</label>

This is an example of a label that did not have the for attribute specified:

<label id="view:_id1:_id3:_id51:requisitionLabel" class="control-label" for="view:_id1:_id3:_id51:dummyTarget">Requisition #</label>




About List