Skip to content

WSubordinateControl

Mark Reeves edited this page Jan 3, 2018 · 9 revisions

WSubordinateControl was a means to provide some simple client-level state control in a Java API. It is a weak mechanism which is an artefact of a past time with flawed framework design paradigms.

Using WSubordinateControl

The WSubordinateControl provides a way to improve the perceived application performance by shifting some basic conditional operations to the client. The WSubordinateControl enables screen logic to be abstracted in such a way that the logic can be executed by both the client-side theme and the server-side WComponent framework.

A word of warning: Use of this control is likely to cause maintenance issues. It is recommended that you use it only for simple situations as overly complex rules become difficult to maintain.

WSubordinateControl does not itself have a UI artefact.

The Java API

The subordinate logic can be expressed in pseudo-code as:

if
   some condition is met
then
   perform some action (if set)
else
   perform some other action (if set)

Conditions are specified using equality tests on input field values and the "And" and "Or" logical operators. Consider the condition expressed in pseudo-code:

if myCheckbox is checked
AND (
    myDropdown's selection = "abc"
    OR
    myTextField's text = "def"
)

Conditions in the subordinate API are built starting from the innermost expression, which in this case are the equality tests in the "Or" condition. The equality checks are built first and placed in an "Or" condition. The "Or" condition is then itself placed in an "And" condition with the remaining equality check:

Equal dropCheck = new Equal(myDropdown, "abc");
Equal textCheck = new Equal(myTextField, "def");
Or or = new Or(dropCheck, textCheck);

boxCheck = new Equal(myCheckBox, true);
And and = new And(boxCheck, or);

The actions can be performed on a single component or a group of components and include:

  • hiding or showing components;
  • enabling or disabling components; and
  • marking components mandatory or optional.

The WSubordinateControl itself does not have a visual representation but it must still be added to a visible section of the WComponents somewhere within the application. To use the WSubordinateControl supply it with the Function objects that implement the screen logic. The snippet below toggles the visibility of a text field depending on whether a check-box is checked.

WCheckBox extraInfoRequired = new WCheckBox();
WTextField extraField = new WTextField();
add(extraInfoRequired);
add(extraField);

Rule rule = new Rule("Extra text required");
rule.setCondition(new Equal(extraInfoRequired, true));
rule.addActionOnTrue(new Show(extraField));
rule.addActionOnFalse(new Hide(extraField));

WSubordinateControl control = new WSubordinateControl();
control.addRule(rule);
add(control);

Alternative syntax

The SubordinateBuilder class provides an easier to read syntax for constructing WSubordinateControls. The previous example can also be implemented as:

WCheckBox extraInfoRequired = new WCheckBox();
WTextField extraField = new WTextField();
add(extraInfoRequired);
add(extraField);

SubordinateBuilder builder = new SubordinateBuilder();
builder.condition().equals(extraInfoRequired, "true"));
builder.whenTrue().show(extraField));
builder.whenFalse().hide(extraField));

WSubordinateControl control = builder.build();
add(control);

Consider a more complex example where the user interface contains two "yes"/"no" radio button groups and two text inputs. A rule which makes the text inputs mandatory if either "yes" option has been selected can be implemented as follows:

SubordinateBuilder builder = new SubordinateBuilder();

builder.condition().equals(radioButtonGroup1, "Yes").or()
  .equals(radioButtonGroup2, "Yes");
builder.whenTrue().setMandatory(textInput1, textInput2);
builder.whenFalse().setOptional(textInput1, textInput2);

add(builder.build());

WSubordinateControl actions

The following actions are available:

  • show;
  • hide;
  • enable;
  • disable;
  • make mandatory;
  • make optional;
  • show 1 ... n of a group of n controls (and hide the others);
  • hide 1 ... n of a group of n controls (and show the others);
  • enable 1 ... n of a group of n controls (and disable the others); and
  • disable 1 ... n of a group of n controls (and enable the others).

Trigger components

WComponents which may be WSubordinateControl triggers implement the SubordinateTrigger interface. The best source of information for a complete list of such components is the JavaDoc for com.github.bordertech.wcomponents.SubordinateTrigger.

Target components

WComponents which may be the target of a WSubordinateControl implement the SubordinateTarget interface. The best source of information for a complete list of such components is the JavaDoc for com.github.bordertech.wcomponents.SubordinateTarget.

Note that not all target components support all types of subordinate control action. For example a WPanel may be hidden (or shown) but not disabled or made mandatory. This is the weakest aspect of WSubordinateControl and the implications of this design have never really been investigated.

Invoking unsupported actions

An action which is applied to a SubordinateTarget which does not implement it is ignored except for disable and enable which are treated as follows.

When a WSubordinateControl action is to disable or enable a target and the target component does not implement the Disableable interface then the behaviour is agreed by convention. The children of the component will be tested recursively until a component that does implement Disableable is found and that component will be actioned. This leads to a problem if the target component is a WDataTable as it implements Disableable but the client code does not allow tables to be disabled as it is not informed if a table is the output of WTable or WDataTable. This is one of the minor reasons why WDataTable was removed.

Further information

Clone this wiki locally