Skip to content
Mark Reeves edited this page Jan 3, 2018 · 17 revisions

WField is the container for each individual label:control pair in a WFieldLayout. It is a simple container for labels and form controls. WField may be the target of a WAjaxControl or WSubordinateControl.

Why use WField

WField is merely a part of WFieldLayout. WFieldLayout is the primary and recommended tool for adding label:control pairs to a WComponents application.

See Why use WFieldLayout for more information.

Creating a WField

WField does not have a public constructor and may be instantiated only from WFieldLayout using one of the addField methods. WFields are always created in the same way: WFieldLayout will determine the correct order of label and input.

// Given WFieldLayout `layout`
// Add a WField with a text label and an input control `input`
WField aField = layout.addField("The label", input);

// Add a WField with a WLabel `label` and an input control `input`
WField anotherField = layout.addField(label, input);

// Add a WField with a WButton `button`. This exists because it is
// common to add a button into the `input` column of a field layout
// but the button is self labelling so should not have a WLabel
// associated with it.
WField buttonField = layout.addField(button);

Under most common circumstances there is no absolute need to get a handle on the WField. This would be necessary if the WField was to be a target for a WSubordinateControl or WAjaxControl or if further methods were to be called on the WField.

Fields without labels

There are genuine use-cases where a group of data input controls may include controls which appear to be unlabelled. A common example of this is an address block which may include several fields for a street address in which only the first is labelled explicitly as illustrated below:

A typical address block

Initially it may seem that the WFields in the illustrated WFieldLayout are created without a label for the second input. This is not the case; in fact the [label|WLabel]] for the second input is hidden. For more details see hiding WLabel.

// with WFieldLayout layout
// and WTextField secondAddressInput
// do not do this
layout.addField(null, secondAddressInput);

// instead do this:
WLabel secondAddressLabel = new WLabel("Address line two");
secondAddressLabel.setHidden(true);
layout.addField(secondAddressLabel, secondAddressInput);

// OR
layout.addField("Address line two",
  secondAddressInput).getLabel().setHidden(true);

Fields with non-Input components

The WFieldLayout methods addField(String, WComponent) and addField(WLabel, WComponent) both accept any WComponent as the "labelled" control; therefore any component may be added to a WFieldLayout though not all need to be labelled.

WLabel will output a UI artefact suited to the labelled WComponent as described in WLabel's HTML output section, so it is not necessary to know what the output of a particular component will be; nor is it necessary to only use a data input control as the added WComponent. The output of a label in this case may still be useful for providing context to the component, so it is not necessarily an error to label a component which does not output data input controls. The output will also be consistent with other labelled (input) controls added to the WFieldLayout.

// With WFieldLayout layout
// and WComponent someComponent
layout.addField("This component has some use", someComponent);

If a WField should contain an unlabelled component which is not a WComponent form control (such as a WPanel or WFieldSet) then the WField may be created using a null WLabel. Note that the inner workings of WComponents makes using null cast to a WLabel slightly more efficient than null cast to a String.

// With WFieldLayout layout
// and WFieldSet fieldset
layout.addField((WLabel) null, fieldset);

Sample appearance

WField is itself transparent and is used to arrange the labels and inputs in a consistent and accessible manner. The illustration shown a sample various WComponents added to WFields in a WFieldLayout.

Sample WFields in a WFieldLayout

Accessing the control and label

WField contains either (or usually both) of a WLabel and another WComponent. This is the case even if the WField is created with the addField(String, WComponent) method.

The input component is accessed using the getField() method; the WLabel using the getLabel() method; and the text content of the WLabel using the getLabelText() method.

Note that null checks should always be implemented before using the result of any of these methods as either or both of the components may be absent.

// with WFieldLayout layout
WComponent someComponent = layout.getChildAt(0);
if (someComponent != null) {
  WField someField = (WField) someComponent;
  WLabel someFieldLabel = someField.getLabel();
  String someFieldLabelText = someField.getLabelText();
  WComponent someFieldComponent = someField.getField();
}

The control

The control (or other WComponent) added to the WField is accessed using getField(). Note WField's getField() method does not return a WField!

The returned control is a WComponent and may need to be cast to the expected type (or interface) to be useful. If, for example, it is expected that the WComponent added to a WField implements Input then the methods of Input may only be used after casting.

// given WField field:
WComponent myComponent = field.getField();
if (myComponent instanceof Input) {
  // do input type stuff
  ((Input) myComponent).setMandatory(true);
}

The label

The different ways of creating a WField will impact on the results of trying to get its label.

// With WFieldLayout layout

// if the WField was created with the WButton version:
WField buttonField = layout.addField(new WButton("Save"));
// then the following will both return null:
buttonField.getLabel();
buttonField.getLabelText();

// if the WField was created:
WField buttonField = layout.addField((String) null, new WButton("Save"));
// or
WField buttonField = layout.addField((WLabel) null, new WButton("Save"));
// then the following will both return null:
buttonField.getLabel();
buttonField.getLabelText();

// ... labelled inputs

// if the WField was created with WLabel someLabel:
WField buttonField = layout.addField(someLabel, new WTextField());
// then the following will return WLabel someLabel:
buttonField.getLabel();
// and the following will return the String content of someLabel:
buttonField.getLabelText();

// if the WField was created with a String:
WField buttonField = layout.addField("Some input", new WTextField());
// then the following will return a WLabel:
buttonField.getLabel();
// and the following will return the String "Some input":
buttonField.getLabelText();

// if the WField was created with an empty String:
WField buttonField = layout.addField("", new WButton("Save"));
// then the following will return a WLabel (with no text content):
buttonField.getLabel();
// and the following will return an empty String (""):
buttonField.getLabelText();

Label text

The text content of the label of a WField may be accessed using getLabelText(). It may also be set (or reset) using setLabelText(String). This is the equivalent of getting the WLabel and getting/setting its text.

// given WField field:
// this will give you the text of the label (or null)
String labelText = field.getLabelText();
// this allows you to reset the label text
field.setLabelText("Some new label text");

There is no shorthand for setting a WLabel hint in WField so this would have to be done by accessing the WLabel.

// given WField field:
WLabel fieldLabel = field.getLabel();
if (null != fieldLabel) {
  String fieldHint = fieldLabel.getHint();
  // and/or
  fieldLabel.setHint("New hint text");
}

// these _could_ be dangerous as they _could_ result in
// throwing a null pointer exception.
field.getLabel().getHint();
field.getLabel().setHint("New hint text");

// If the WField has just been created it should be safe.
// Given WDateField purchaseDateField with a `max` constraint:
fieldLayout.addField("Date of purchase", purchaseDateField)
  .getLabel().setHint("must be on or before today");

Input validation

A FieldValidator may be added to a WField to undertake a custom validation rule if the added WComponent is an instance of Input. This is the same as adding the validator directly to the input component and, under most circumstances, it is recommended that any custom validation be added directly to an Input component rather than by proxybia the WField. If a custom validation scenario is attached to a WField then it cannot be performed as part of Client side validation unless it directly replaces a built-in validation scenario such as a test for maximum allowed input.

// Given WField field and FieldValidator validator
field.addValidator(validator);

The diagnostics from a FieldValidator are, by default, attached to a WMessages.

Warning messages

A warning level message agains a WField or its component (such as created by a FieldValidator) may be output in a WFieldWarningIndicator. This WFieldWarningIndicator may then be accessed from the WField. The WFieldWarningIndicator may then be used to manipulate the diagnostic messages shown to the user.

// Given WField field
WFieldWarningIndicator = field.getWarningIndicator();

Controlling input width

The inputWidth property may be used to adjust the apparent width of the WComponent in the WField. It accepts integer values (0-100) and translates these as a percentage of the width of the parent container's content box. The available space will be determined by the parent WFieldLayout's labelWidth property. Note that in the default theme only inputWidth 100 is explicitly supported. Any use of inputWidth will have the same effect as using 100. To extend this see theme development below.

If this property is used at all then it is almost always set to 100 to make the control fill the available space; the following illustration shows two WTextField components each in a WField, the first WField has inputWidth 100 and neither WTextField has a predetermined size.

Screenshot showing two WTextFields the first is in a WField with inputWidth 100

In most cases setting an inputWidth will make the control in the WField occupy the requested space. The following are exceptions:

  • radio buttons and check boxes are unaffected by this setting;
  • file upload fields are unaffected by these fields in all W3C standards compliant user agents;
  • WDropdown, WMultiDropdown) and WSingleSelect (if it has its rows property set to 1) may be rendered unusable or inaccessible if they are placed in a WField with this property set if the requested width is less than the native width of the element if the browser is Internet Explorer before version 9.
// given WField field
field.setInputWidth(100);

// ... OR (more compact given most uses of WFieldLayout):
// Set inputWidth on a WField in WFieldLayout `layout`
layout.addField(someLabel, someInput).setInputWidth(100);

Hiding

A WField may be hidden on page load. This property is determined by a WSubordinateControl. When hidden the WField is not available to any compliant user agent. It is present in the source and is not obscured in any way.

Theme development

Support for inputWidth may be extended. Each WField which has inputWidth set has a class value wc_fld_inpw_NNN where NNN is a number from 1 to 100. These classes may be used to set a width and max-width on the input part of the field's output. The default Sass has a skeleton to do this based on variables see $wc-fld-use-inputwidth in /src/main/sass/vars/_fieldlayout.scss.

Related components

Further information

Clone this wiki locally