-
Notifications
You must be signed in to change notification settings - Fork 17
WCheckBoxSelect
WCheckBoxSelect is a component for creating a set of related check boxes based on a list of options. The checkboxes then form a single multiple selection (0...n of n) component with support for implicit null selection.
- Why use WCheckBoxSelect
- Creating a WCheckBoxSelect
- Accessibility
- Selection constraints
- Appearance
- HTML output
- Read-only
- Disabling
- Hiding
- Default submit button
- Testing
- Related components
- Further information
WCheckBoxSelect is most useful for choosing 0 to n
of n
options where n
is quite small (a rough rule of thumb would be below 10 but this may be increased if using a columnar layout).
If the common use case involves selecting more than half of the options then WSelectToggle is a useful addition.
Groups of checkboxes may be created using WCheckBox rather than WCheckBoxSelect.
WCheckBoxSelect is the preferred tool for creating a single coherent set of checkbox controls. The output of a WCheckBoxSelect will always form a single block in the UI. In addition the options used to create the individual check boxes and their labels are limited to string values.
There are some common scenarios where WCheckBoxSelect is not appropriate.
- WCheckBoxSelect cannot be used if the labels for checkboxes are to contain anything other than simple text. So to include an image in the label, for example, will require a group of WCheckBox components.
- WCheckBoxSelect is limited to having all checkboxes in the same enabled, read-only and hidden states. If use cases require some checkboxes to be in states different from others then a group of WCheckBox components will need to be used.
- WCheckBoxSelect should not be used where the number of choices is large. In this case it may be better to use WMultiSelect or WMultiSelectPair. WCheckBoxSelect does not allow the options to be sub-divided into groups. If this is required then WMultiSelect, WMultiSelectPair or WTree should be used.
- WCheckBoxSelect cannot be used if the check boxes are not in a single block in the UI. Note, however, that this will cause usability and accessibility issues which need to be carefully managed. A common scenario where this is the case is a table column of grouped check boxes. In this case a group of WCheckBox components will need to be used.
WCheckBoxSelect may be instantiated using an Object Array, a table Object or a List. After instantiation the options may be added as a List or Object Array.
// a WCheckBoxSelect with no options
WCheckBoxSelect cbSelect = new WCheckBoxSelect();
// given a list<?> options
cbSelect = new WCheckBoxSelect(options);
// or given an Object[] optionArray
cbSelect = new WCheckBoxSelect(optionArray);
// or using a lookupTable table
cbSelect = new WCheckBoxSelect(table);
The output of the WCheckBoxSelect limits each option to a simple String which is XML escaped. The options are used to report what values were selected by the user and to produce the label for each individual checkbox. The options may not contain markup. If your UI has a requirement for labels which contain HTML markup (for example to add an image) then a group of WCheckBox components should be used wrapped in a WFieldSet (see compared with a group of WCheckBox components below).
Each option in a WCheckBoxSelect must be a string which indicates, to the user, the option being selected. This means the options' values must be understandable such as "apple", "banana", "cumquat" rather than representational of application data such as 0
, 1
, 2
.
The WCheckBoxSelect, if not read-only, must itself be labelled. This represents the "question" to which the options represent possible "answers". This may be done using:
- WLabel or by using the WCheckBoxSelect in a WField (preferred) this is required if the label must be visible in the UI; or
- using the toolTip property if the label does not have to be visible in the UI; or
- using the accessibleText property.
If the WCheckBoxSelect has a visible label and is not in a WField then the WLabel should be added to the UI immediately before or above the WCheckBoxSelect.
WCheckBoxSelect cbSelect = new WCheckBoxSelect();
WLabel cbSelectLabel = new WLabel("Select something", cbSelect);
// ...
add(cbSelectLabel);
add(cbSelect);
A WCheckBoxSelect which is not appropriately labelled may display an unlabelled control warning.
A label for a WCheckBoxSelect is implemented as a HTML legend element immediate child of the WCheckBoxSelect's fieldset.
If the WCheckBoxSelect is associated with a WLabel (including by being added to a WField) then the content of the label is also output in-situ as a HTML span element. This span is then marked as aria-hidden="true"
to prevent double reading in PC mode but has scripted helpers to ensure it behaves in a manner equivalent to a legend (for access key support) and a label (for mouse users).
This arrangement allows the use of semantically correct and specification compliant grouping using a fieldset as well as design and usability consistency for complex UIs where a compound control such as a WCheckBoxSelect is arranged in a layout which also includes simple form controls and their labels. It is illustrated below.
Where a WCheckBoxSelect has its toolTip property set but is not associated with a WLabel the content of the toolTip is placed in the legend and rendered out of viewport.
If the WCheckBoxSelect has selection constraints then there must be an indication of these constraints somewhere in the UI and available to all users. The appropriate place for this information is in the WLabel hint.
If the control is mandatory this indication is automatically generated within the legend element and the legend (if visible) and pseudo-label (if present) are both decorated accordingly.
See toolTip. This property may be used to create an accessible label equivalent for the component if the application design precludes the presentation of a visible label. This is strongly discouraged for complex multi-input components like WCheckBoxSelect and should probably be avoided.
cbSelect.setToolTip("Some further context to this selection.");
WCheckBoxSelect may have accessible text applied as information additional to the visible legend/pseudo-label text. This should be used with care and restraint as it may result in less accessible applications.
cbSelect.setAccessibleText("Some further context to this selection.");
The checkboxes in a WCheckBoxSelect may be navigated using the TAB
key as is usual for a group of checkboxes or by using the arrow keys.
WCheckBoxSelect has a feature where a range of checkboxes may be selected/deselected by selecting/deselecting the checkbox at the beginning of the range then holding the SHIFT
key whilst selecting/deselecting the checkbox at the end of the range. This feature has been around for a very long time but is not exposed in the UI. I am not entirely sure why this is the case.
A WLabel for a WCheckBoxSelect may be given an access key to provide rapid keyboard access.
A WCheckBoxSelect in an enabled, interactive state may be set as the default focus point for a page. If this is specified it must comply with accessibility principles regarding focus and not put users into a position where they may skip content required for full understanding of the current view. When the component is set as focussed the first available check box will be focussed. See Setting focus for more information.
// given WCheckBoxSelect cbSelect
// set as default focus point
cbSelect.setFocussed();
A WCheckBoxSelect may be constrained to accept a minimum or maximum number of selected options and/or to be mandatory.
A WCheckBoxSelect may be marked as being a mandatory field in the UI and is set using setMandatory(boolean)
or by a WSubordinateControl. A WLabel associated with the component is also decorated with a visual indicator that the component is mandatory. When a WCheckBoxSelect is marked as mandatory no individual check box is mandatory. Mandatory indicates that at least one option from the set must be selected. This property does not apply if the WCheckBoxSelect is in a read-only state.
// given WCheckBoxSelect cbSelect ...
cbSelect.setMandatory(true);
The mandatory state of a control may be set by a WSubordinateControl in which case there is no need to explicitly set the mandatory state on the control.
WCheckBoxSelect may enforce a minimum number of options which should be selected if any selection is made. It should never be specified as 1; if the component must have a selection then it should be made mandatory, if the component is optional and the minimum number of selections, if any are made, is 1 then setting the min property is superfluous and merely adds unnecessary testing overhead. If this property is set then the minimum number of options which are to be selected should be indicated in the WLabel for the component. This property does not apply if the WCheckBoxSelect is in a read-only state.
// given WCheckBoxSelect cbSelect
// set the minimum selection to 3
cbSelect.setMinSelect(3);
Setting a minimum selection will not automatically make the component mandatory. The minimum selection is validated only if the user has made any selection. Make the component mandatory to force selection. Minimum selection and mandated selection may be used in conjunction to enforce a required minimum selection by the user.
// given WCheckBoxSelect cbSelect
// set the required minimum selection to 3
cbSelect.setMandatory(true);
cbSelect.setMinSelect(3);
WCheckBoxSelect may enforce a maximum number of options which may be selected. Whilst undertaking selection the user may select more than max so long as no more than max is selected at the time of submission. This allows a user to, for example, use a WSelectToggle to select all options then deselect those which are not required. This makes selection quicker if more than half of the available options are to be selected. This property does not apply if the WCheckBoxSelect is in a read-only state.
If this property is set then an indication of the maximum number of allowed selections should be given to the user within the associated WLabel.
// given WCheckBoxSelect cbSelect
// set the maximum selection to 3
cbSelect.setMaxSelect(3);
WCheckBoxSelect will render a group of checkboxes and their labels. The actual appearance of the checkboxes is platform and (to a less extent) browser dependent. The arrangement of checkboxes is determined by the layout. The group of checkboxes are wrapped in a fieldset element; the fieldset border can be turned on and off.
The illustration below shows a typical output on OS X.
Variations on the appearance are illustrated in the section managing appearance.
The checkboxes (and their label) may be laid out in several ways using a layout
property. There are three options:
-
FLAT
in which the options are laid out horizontally: -
STACKED
in which the options are laid out vertically (this is the default): -
COLUMN
in which the options are laid out in one or more columns as determined by the layoutColumnCount property:
The property is set using the Java method setButtonLayout(WCheckBoxSelect.Layout)
. If not set then WCheckBoxSelect.Layout.STACKED
is used.
WCheckBoxSelect cbSelect = new WCheckBoxSelect();
// to set Layout.FLAT
cbSelect.setButtonLayout(WCheckBoxSelect.Layout.FLAT);
If the layout is WCheckBoxSelect.Layout.COLUMN
then the number of columns may be specified. The number of options in each column is the ceiling of the number of options divided by the number of columns. If the number of options is not a multiple of the number of columns then the last column will have fewer options than the other columns. If this is not set then all of the options are placed into a single column equivalent to WCheckBoxSelect.Layout.STACKED
.
// To set a layot using three columns:
WCheckBoxSelect cbSelect = new WCheckBoxSelect();
cbSelect.setButtonLayout(WCheckBoxSelect.Layout.COLUMN);
cbSelect.setButtonColumns(3);
The output when the column count is set to three will be something like:
WCheckBoxSelect (when not in a read-only state) is wrapped in a HTML fieldset element. This element may have a border or other default styling (dependent on your theme). This border/default styling may then be enabled or disabled using the setFrameless(boolean)
method.
WCheckBoxSelect cbSelect = new WCheckBoxSelect();
// to set frameless
cbSelect.setFrameless(true);
This is commonly used if the WCheckBoxSelect is added to a WFieldLayout with a FLAT layout where the legend is visually replaced with a placeholder to look like other field labels. By default this property does not apply if the WCheckBoxSelect is in a read-only state as that state does not generally output an element usually styled with a border.
-
A frameless WCheckBoxSelect:
-
A WCheckBoxSelect in a WFieldLayout:
-
A frameless WCheckBoxSelect in a WFieldLayout:
WCheckBoxSelect's limited palate of appearance options are designed to ensure a high degree of consistency, accessibility and usability. The design and even behaviour of WCheckBoxSelect may be amended on an instance-by instance or application-by-application basis using custom CSS and/or custom JavaScipt. This display/behaviour is then attached to a class-name added using the htmlClass property. For more information see WComponents HTML class property.
WCheckBoxSelect cbSelect = new WCheckBoxSelect();
// to set class attribute values on the HTML output
cbSelect.setHtmlClass("myMagicClass anotherMagicClass");
Default responsive design for WCheckBoxSelect applies if the layout is WCheckBoxSelect.Layout.COLUMN
. When viewed on a narrow viewport the column count is ignored and all checkbox/label pairs are displayed in a single column. See Responsive Design for more information.
WCheckBoxSelect is a compound form control, therefore it outputs a HTML fieldset element. The check boxes are then placed inside this fieldset. The arrangement of the check boxes within the fieldset is determined by the layout and layoutColumnCount properties.
In a read-only state WCheckBoxSelect will output HTML dependent upon the number of selected options:
- when the number of selected options is zero or one the WCheckBoxSelect will output a HTML span element which (if exactly one option is selected) will contain the text equivalent of the selected option;
- when the number of selected options is greater than one the WCheckBoxSelect will output a HTML div element containing one or more unordered lists of the selected options and in this case WCheckBoxSelect outputs non-phrasing content.
Unlike WCheckBox no graphic marker is used to indicate the selected state of the read-only options. This is because only the selected option(s) are output and the label for each check box is inextricably linked with the check box.
WCheckBoxSelect outputs non-phrasing content and form-related interactive content and must not be used in any context which forbids these content categories: see WComponent content models and WComponent form controls.
WCheckBoxSelect appears as a text representation of the control when in a read-only state. The control is not able to be interacted with by the user and does not return any value back to the application.
In this state only those options which are selected according to the last submitted state of the control are output to the UI.
-
A WCheckBoxSelect in the read only state with many selected options:
-
A WCheckBoxSelect in the read only state with the same options but only one selected option:
-
A WCheckBoxSelect in the read only state with the same options but no selected option:
-
A WCheckBoxSelect in the read only state with many selected options and column layout:
A WCheckBoxSelect in a readOnly state may be the target of a WSubordinateControl or WAjaxControl. If it is the target of an AJAX action its state may be changed to remove the readOnly setting.
A WCheckBoxSelect may be disabled on page load. When disabled the WCheckBoxSelect will not respond to user input or interaction and all check boxes will be disabled. This property does not apply if the WCheckBoxSelect is in a read-only state. The selected state of all check boxes in this case is the same as if they were all unchecked. This is important: a disabled check box is not checked.
This property may be used in conjunction with WSubordinateControl controls to enable or disable content without making another server call. If the control is disabled/enabled by a WSubordinateControl then there is no need to explicitly disable the control: the state will be calculated by the WSubordinateControl's rules.
A WCheckBoxSelect should not be output in a disabled state if the intent is to not allow the user to enable the control through the use of a WSubordinateControl. In this case it is more appropriate to use the read-only state.
A disabled check box has no rational checked state: a checked, disabled check box is the same as an unchecked disabled check box and both are deemed unchecked.
A WCheckBoxSelect may be hidden on page load. When hidden the WCheckBoxSelect is not available to any compliant user agent. It is present in the source and is not obscured in any way. This property is determined by a WSubordinateControl. When a WCheckBoxSelect is hidden any WLabel associated with it is also hidden.
A WCheckBoxSelect may be associated with a WButton in a way that if the user hits the ENTER
key whilst any checkbox in the WCheckBoxSelect has focus then the nominated WButton will be deemed to be the control which submits the form to the server. This is discussed in more detail in Implicit form submission.
// given WCheckBoxSelect cbSelect and WButton button
// set as button as the default submit button
cbSelect.setDefaultSubmitButton(button);
This setting is not used if the WCheckBoxSelect is in a read-only state or is a trigger for a WAjaxControl.
WCheckBoxSelect may be manipulated in Selenium tests using the com.github.bordertech.wcomponents.test.selenium.element.SeleniumWCheckBoxSelectWebElement
extension of WebElement
.
The best way to get a WCheckBoxSelect from a test view is by using SeleniumWComponentsWebDriver which has a method findWCheckBoxSelect(By)
. This can be used in conjunction with com.github.bordertech.wcomponents.test.selenium.ByLabel
, for example, to find a WCheckBoxSelect using its WLabel's text.
@Test
public void testFindByLabel() {
SeleniumWComponentsWebDriver driver = getDriver();
String labelText = "Select some of these";
SeleniumWCheckBoxSelectWebElement checkBoxSelect =
driver.findWCheckBoxSelect(new ByLabel(labelText, false));
}
SeleniumWCheckBoxSelectWebElement
extends SeleniumCheckableGroupInputWebElement and provides helpers to deselect
and toggle
options. Options may be interacted with based on their index, label text or by accessing the option's WebElement obtained from one of the getOption methods.
See SeleniumCheckableGroupInputWebElement for information regarding accessing, selecting, clicking and determining the selected state of options.
An individual option may be deselected in a Selenium test.
// given SeleniumWCheckBoxSelectWebElement element
// to deselect the 'nth' option:
element.deselect(n);
// to deselect the NSW option:
element.deselect("New South Wales");
// to deselect a previously obtained option WebElement `option`
element.deselect(option);
An individual option may have its selected state toggled in a Selenium test. For WCheckBoxSelect this is the equivalent of "clicking" the option. In many real scenarios it may be better to use clickNoWait() than toggle
// given SeleniumWCheckBoxSelectWebElement element
// to toggle the 'nth' option:
element.toggle(n);
// to deselect the NSW option:
element.toggle("New South Wales");
// to deselect a previously obtained option WebElement `option`
element.toggle(option);