-
Notifications
You must be signed in to change notification settings - Fork 17
WField
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
- Creating a WField
- Sample appearance
- Accessing the control and label
- Input validation
- Controlling input width
- Hiding
- Theme development
- Related components
- Further information
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.
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.
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:
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);
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);
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.
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 (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 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();
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");
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.
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();
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.
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 to1
) 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);
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.
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
.