A validator is a function that takes in the fields new value, and then acts on it. They are a simple way to customize a field. They allow you to trigger functionality when a field's value changes, modify input, or limit which values are acceptable.
Some common examples:
- Restricting a text field to only accept letters.
- Requiring that a text field be non-empty.
- Requiring that a date be in the future.
- Modifying a block's shape based on a dropdown.
Types of validators
Validators execute at different times depending on what kind of validator they are.
Class validators are part of a field type's class definition, and are usually used to restrict the type of value allowed by the field (e.g. number fields only accept numeric characters). Class validators are run on all values passed to the field (including the value passed to the constructor).
For more information about class validators see the Implementing a class validator section in Creating a Custom Field.
Local validators are defined at the time of a field's construction. Local validators run on all values passed to the field except the value passed to the constructor. This means they run on:
- Values contained in XML.
- Values passed to setValue.
- Values passed to setFieldValue.
- Values changed by the user.
Class validators are run before local validators because they act like gatekeepers. They make sure that the value is of the correct type before passing it on.
For more information about the sequence of value validation, and values in general see Values.
Registering a local validator
Local validators can be registered in two ways:
- Directly added in a field's constructor.
Blockly.Blocks['validator_example'] = {
init: function() {
// Remove all 'a' characters from the text input's value.
var validator = function(newValue) {
return newValue.replace(/\a/g, '');
};
this.appendDummyInput()
.appendField(new Blockly.FieldTextInput('default', validator));
}
};
- With setValidator.
Blockly.Blocks['validator_example'] = {
init: function() {
// Remove all 'a' characters from the text input's value.
var validator = function(newValue) {
return newValue.replace(/\a/g, '');
};
var field = new Blockly.FieldTextInput('default');
field.setValidator(validator);
this.appendDummyInput().appendField(field);
}
};
Either of the above methods can be wrapped in an extension, to support the JSON format.
The field's value may be very different depending on the type of field being validated (e.g. a number field will store a number, while a text input field will store a string) so it is best to read the documentation for your specific field before creating a validator.
Return values
The return value of the validator determines what the field does next. There are three possibilities:
Modified Return Value
A modified or different value, which then becomes the field's new value. This is often used to clean up a value, such as by removing trailing whitespace.
Example of a Modifying Validator:
// Remove all 'a' characters from the text input's value.
var validator = function(newValue) {
return newValue.replace(/\a/g, '');
};
Null Return Value
Null, which means the given value is invalid. In most cases the field will
ignore the input value. The exact behaviour is specified by the field's
doValueInvalid_
function.
Example of a Nulling Validator:
// Any value containing a 'b' character is invalid. Other values are valid.
var validator = function(newValue) {
if (newValue.indexOf('b') != -1) {
return null;
}
return newValue;
};
Undefined Return Value
Undefined (or no return statement) or the input value, which means that the input value should become the field's new value. These types of validators generally act as change listeners.
Example of a Listener Validator:
// Log the new value to console.
var validator = function(newValue) {
console.log(newValue);
};
Note once again how the display text does not necessarily reflect the field's value.
Value of this
Inside of a validator this
refers to the field, not the block. If you need to
access the block inside of a validator use the getSourceBlock
function. You can
also use the
bind function
to set the context within which the validator is called.
Sample code using getSourceBlock
:
Blockly.Blocks['colour_match'] = {
init: function() {
this.appendDummyInput()
.appendField(new Blockly.FieldColour(
null, this.validate
), 'COLOUR');
this.setColour(this.getFieldValue('COLOUR'));
},
validate: function(colourHex) {
this.getSourceBlock().setColour(colourHex);
}
};
Sample code using bind:
Blockly.Blocks['colour_match'] = {
init: function() {
this.appendDummyInput()
.appendField(new Blockly.FieldColour(
null, this.validate.bind(this)
), 'COLOUR');
this.validate(this.getFieldValue('COLOUR'));
},
validate: function(colourHex) {
this.setColour(colourHex);
}
};