Skip to content

Constraints

Roberto Prevato edited this page Dec 28, 2017 · 13 revisions

Constraints in the DataEntry library are functions that are called on keypress, and disallow to input certain values. Constraints are used by built-in DomBinder class and should be ignored by programmers who want to let other libraries/frameworks handle DOM manipulation.

They are well supported on desktop browsers, but likely to require special attention for mobile devices. An example of constraint, is one that doesn't allow to input letters in a field that is supposed to accept only digits. Constraints are not a replacement for validation rules, since users can still insert values using copy paste, and this should not be prevented, but make sense in many real life situations.

If built-in DOM classes are used, constraints can be used to limit input on keypress.

Global constraints rules

Rules defined in Constraints.Rules are common across all instances of DataEntry. Below example demonstrates the definition of new global constraint rules.

import DataEntry from "dataentry"
import DataEntryDom from "dataentry/dom"

// get reference to constraints
const Constraints = DataEntryDom.Constraints;

// get reference to a provided utility function that returns true for combinations of characters that should
// always be allowed (e.g. Copy-paste, cut, etc.)
const permittedCharacters = Constraints.utils.permittedCharacters;
const stringFromCode = Constraints.stringFromCode;

// defines a new constraint rule that disallow inserting "0" inside an input field
Constraints.Rules.noZero = function (e, c) {
  // e is the original event object, c is the code of keypress event
  // this is a keypress event handler
  var c = (e.keyCode || e.charCode), key = stringFromCode(c);
  if (!permittedCharacters(e, c) && key === "0") return false;
  return true;
}

// then, somewhere else in code:
var a = new DataEntry({
  schema: {
    // the constraint rule can then be used with multiple fields defined in the dataentry schema:
    "field_a": { validation: ["none"], constraint: "noZero" },
    "field_b": { validation: ["required"], constraint: "noZero" }
  }
})

Instance specific constraint rules

Instance specific constraints can also be defined when creating the instance of DataEntry:

import DataEntry from "dataentry"
import DataEntryDom from "dataentry/dom"

// get reference to constraints
const Constraints = DataEntryDom.Constraints;

// get reference to a provided utility function that returns true for combinations of characters that should
// always be allowed (e.g. Copy-paste, cut, etc.)
const permittedCharacters = Constraints.utils.permittedCharacters;
const stringFromCode = Constraints.stringFromCode;

// get reference to Formatter class
const Formatter = DataEntry.Formatter;

var a = new DataEntry({
  // specify one additional validation rule for the instance of dataentry:
  constraintRules: {
    noZero: function (value) {
      // e is the original event object, c is the code of keypress event
      // this is a keypress event handler
      var c = (e.keyCode || e.charCode), key = stringFromCode(c);
      if (!permittedCharacters(e, c) && key === "0") return false;
      return true;
    }
  },
  schema: {
    // the constraint rule can then be used with multiple fields defined in the dataentry schema:
    "field_a": { validation: ["none"], constraint: "noZero" },
    "field_b": { validation: ["required"], constraint: "noZero" }
  }
})

ES6 class definition

Constraint rules can also be defined using the ES6 class syntax, defining new types of DataEntry. NB: the DataEntry class must be configured to use the built-in DomBinder class.

import DataEntry from "dataentry";

// example:
class PaymentsAreaDataEntry extends DataEntry {
  // {...} implement here constructor to extend the rules for this kind of DataEntry
  // alter `this.binder.constraints` to add new rules for a class of DataEntry
}

Constraint rules can be defined:

  • explicitly
  • implicitly

Explicit constraints

Constraints can be declared explicitly inside each dataentry schema, for example:

      schema: {
        foo: {
          validation: ["required"],
          constraint: "integer"     // explicit constraint for `foo` field
        }

Implicit constraints

If the DataEntry option useImplicitConstraint is different than false, then constraints rules can be implicitly set when a validation rule has a name that matches the name of a constraint rule. For example:

      schema: {
        foo: {
          validation: ["integer"]
        },

Since a built-in constraint with name integer is defined inside the Constraints object, it will be automatically used to limit the kind of input the field can receive.

Useful functions

The DataEntry library offers some useful functions that can be reused when implementing custom constraint rules:

  • permittedCharacters - to be used with a keypress event, it returns a value indicating whether a character or a combination of characters should always be allowed (for example: Ctrl+A to select all, or Ctrl+X to cut)
  • foreseeValue - to be used with a keypress event on a field with value property, it returns the value that the field would assume if the event gets through. In other words, it foresees the value that the input field will have after the given keypress event. Useful to support properly paste, cut, or simply keypress validation when more than one character is selected.
  • stringFromCode - simple shortcut for String.fromCharCode function
  • match - simple shortcut for regex match on string