Archive | July 2016

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

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>
Advertisements

XPages Tip: Overriding, Concatenating, and Conditionally Adding Control Properties via a Theme

Themes are commonly-used in XPages applications to include resources needed throughout an application, but they can also be a powerful tool for consistently applying application-wide control settings. In this post, I’ll explain the difference between different modes for applying a control property and link to a corresponding post with a practical example.

1. Overriding a Control Property

In this post, I showed how to use the theme to add a class to all labels in an application to pick up Bootstrap styling without having to set the class on each individual label.

Here’s an example of the theme code to make it happen:

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

When a page loads, the theme is applied to the page and all label controls are updated as the page is rendered.

  • Line 2 is directing it to apply to all Label controls throughout the application. (This is using a theme ID that’s predefined for the label control, as noted in the Mastering XPages book.)
  • Line 4 specifies that it’s updating the styleClass property of the controls.
  • Line 5 specifies the control-label class to add to each label. (This is the class name that Bootstrap styling looks for.)
  • Line 3 is the variable for this post. This example starts with the setting the override mode. This mode will set the class to the specified value on all label controls, overriding anything that may have been set when the control was added on an XPage or custom control.

2. Concatenating a Control Property

Instead of overriding the property on all controls, another option is to concatenate the specified value to any existing value specified on each instance of the control.

<property mode="concat">

In this case, if there was a label control that already had a class specified, the control-label class would be added to it (after a space) so the label would have both classes.

If the label control did not have a class, then the specified class would be added.

3. Conditionally Applying a Control Property

The last option is not to specify a mode at all.

<property>

In this case, it will not do anything to a label control that already has a class specified, but it will add the specified class to any label control that does not have one.

Take a look at for a practical example of each of these methods and how the distinction between these methods matters.