10 Validate and Convert Input

Oracle JET includes validators and converters on a number of Oracle JET editable elements, including oj-combobox, oj-input*, and oj-text-area. You can use them as is or customize them for validating and converting input in your Oracle JET app.

Some editable elements such as oj-checkboxset, oj-radioset, and oj-select have a simple attribute for required values that implicitly creates a built-in validator.

Note:

The oj-input* mentioned above refers to the family of input components such as oj-input-date-time, oj-input-text, and oj-input-password, among others.

About Oracle JET Validators and Converters

Oracle JET provides converter classes that convert user input strings into the data type expected by the app and validator classes that enforce a validation rule on those input strings.

For example, you can use Oracle JET's IntlDateTimeConverter to convert a user-entered date to a date-only ISO string and then use DateTimeRangeValidator to validate that input against a specified date range. If the converters or validators included in Oracle JET are not sufficient for your app, you can create custom converters or validators.

About Validators

All Oracle JET editable elements support a value attribute and provide UI elements that allow the user to enter or choose a value. These elements also support other attributes that you can set to instruct the element how to validate its value.

An editable element may implicitly create a built-in converter and/or built-in validators for its normal functioning when certain attributes are set. For example, editable elements that support a required property create the required validator implicitly when the property is set to true. Other elements like oj-input-date, oj-input-date-time, and oj-input-time create a datetime converter to implement its basic functionality.

About the Oracle JET Validators

The following table describes the Oracle JET validators and provides links to the API documentation:

Validator Description Link to API Module

DateTimeRangeValidator

Validates that the input date is between two dates, between two times, or within two date and time ranges

DateTimeRangeValidator

ojvalidation-datetimerange

DateRestrictionValidator

Validates that the input date is not a restricted date

DateRestrictionValidator

ojvalidation-daterestriction

LengthValidator

Validates that an input string is within a specified length

LengthValidator

ojvalidation-length

NumberRangeValidator

Validates that an input number is within a specified range

NumberRangeValidator

ojvalidation-numberrange

RegExpValidator

Validates that the regular expression matches a specified pattern

RegExpValidator

ojvalidation-regexp

RequiredValidator

Validates that a required entry exists

RequiredValidator

ojvalidation-required

About Oracle JET Component Validation Attributes

The attributes that a component supports are part of its API, and the following validation specific attributes apply to most editable elements.

Element Attribute Description

converter

When specified, the converter instance is used over any internal converter the element might create. On elements such as oj-input-text, you may need to specify this attribute if the value must be processed to and from a number or a date value.

countBy

When specified on LengthValidator, countBy enables you to change the validator’s default counting behavior. By default, this property is set to codeUnit, which uses JavaScript's String length property to count a UTF-16 surrogate pair as length === 2. Set this to codePoint to count surrogate pairs as length ===1.

max

When specified on an Oracle JET element like oj-input-date or oj-input-number, the element creates an implicit range validator.

min

When specified on an Oracle JET element like oj-input-date or oj-input-number, the component creates an implicit range validator.

required

When specified on an Oracle JET element, the element creates an implicit required validator.

validators

When specified, the element uses these validators along with the implicit validators to validate the UI value. Can be implemented with Validators or AsyncValidators to validate the user input on the server asynchronously.

Some editable elements do not support specific validation attributes as they might be irrelevant to its intrinsic functioning. For example, oj-radioset and oj-checkboxset do not support a converter attribute since there is nothing for the converter to convert. For an exact list of attributes and how to use them, refer to the Attributes section in the element’s API documentation. For Oracle JET API documentation, see API Reference for Oracle® JavaScript Extension Toolkit (Oracle JET). Select the component you're interested in viewing from the API list.

About Oracle JET Component Validation Methods

Oracle JET editable elements support the following methods for validation purposes. For details on how to call this method, its parameters and return values, refer to the component’s API documentation.

Element Method Description

reset()

Use this method to reset the element by clearing all messages and messages attributes - messagesCustom - and update the element’s display value using the attribute value. User entered values will be erased when this method is called.

validate()

Use this method to validate the component using the current display value.

For details on calling an element's method, parameters, and return values, see the Methods section of the element's API documentation in API Reference for Oracle® JavaScript Extension Toolkit (Oracle JET). You can also find detail on how to register a callback for or bind to the event and for information about what triggers the events. Select the component you're interested in viewing from the API list.

About Oracle JET Converters

Oracle JET provides converters to convert date, date-time, number, color, and string.

These converters extend the Converter object which defines a basic contract for converter implementations. The converter API is based on the ECMAScript Internationalization API specification (ECMA-402 Edition 1.0) and uses the Unicode Common Locale Data Repository (CLDR) for its locale data. Both converters are initialized through their constructors, which accept options defined by the API specification. For additional information about the ECMA-402 API specification, see https://www.ecma-international.org/publications-and-standards/standards/ecma-402/. For information about the Unicode CLDR, see http://cldr.unicode.org.

The Oracle JET implementation extends the ECMA-402 specification by introducing additional options. You can use the converters with an Oracle JET component or instantiate and use them directly on the page. Each converter has a ConverterOptions type definition that specifies the conversion options it supports. The following table describes the available converters and provides a link to the API documentation for each converter, including detailed descriptions of the properties supported by each converter’s ConverterOptions type definition.

Converter Description Link to API

ColorConverter

Converts Color object formats

ColorConverter

IntlDateTimeConverter

Parses a string into an ISO string format (yyyy-mm-dd) or converts an ISO string into a standard string format. For example:

  • 10/12/2020 ---> 2020-10-12
  • 2020-10-12 ---> 10/12/2020

IntlDateTimeConverter

NumberConverter

Converts a string into a number and formats a number into a locale-specific string

NumberConverter

BigDecimalStringConverter

Converts a big-decimal string into a locale-specific string. Use for very large numbers (greater than Number.MAX_SAFE_INTEGER) and numbers with large scale (more than 17 fractional digits). Can only be used with components that expect a string value, such as oj-c-input-text.

BigDecimalStringConverter

LocalDateConverter

Converts a date-only ISO string to a formatted string or a string to a date-only ISO string

LocalDateConverter

In addition to the API documentation, see the following demos in the Oracle JET Cookbook that show converters in use:

The Oracle JET converters support lenient number and date parsing when the user input does not exactly match the expected pattern. The parser does the lenient parsing based on the leniency rules for the specific converter. For example, both NumberConverter and BigDecimalStringConverter remove unexpected characters. The ConverterOptions type definition typically includes a lenientParse property that you can set to none so that user input matches the expected input or an exception is thrown. For specific details, see the API documentation for the converter that you are using.

The resource bundles that hold the locale symbols and data used by the Oracle JET converters are downloaded automatically based on the locale set on the page when using RequireJS and the ojs/ojvalidation-datetime or ojs/ojvalidation-number module. If your app does not use RequireJS, the locale data will not be downloaded automatically.

You can use the converters with an Oracle JET component or instantiate and use them directly on the page.

Use Oracle JET Converters with Oracle JET Components

Oracle JET components that accept user input, such as oj-c-input-date-text, already include an implicit converter that parses user input. However, you can also specify an explicit converter on the component that will be used instead when converting data.

In the following example, taken from the Overview demo for the oj-c-input-date-text component in the Oracle JET Cookbook, an error message displays if you enter "abc" while the component accepts an input of "12/25/24" and renders it as "12/25/2024" using its implicit converter.

The error that the converter throws when there are errors during parsing or formatting operations is represented by the ConverterError object, and the error message is represented by an object of type Message. The messages that Oracle JET converters use are resources that are defined in the translation bundle included with Oracle JET.


oj-c-input-date-text with implicit converter

You can also specify the converter directly on the component's converter attribute, if it exists. For example, the oj-c-input-date-text component uses the converter attribute to change the date style that the component renders to one of the converter options supported by LocalDateConverter.


oj-c-input-date-text with explicit converter

The Oracle JET Cookbook includes implementations of the options discussed here. See:

Understand Time Zone Support in Oracle JET

Oracle JET input components, such as oj-input-date-time, support local time zone input. You can enable time zone support by using Oracle JET's IntlDateTimeConverter, which relies on JavaScript's Intl.DateTimeFormat API.

In the following image, the Input Date Time component’s converter attribute references code that renders the input time of 2013-12-02T04:00:00Z appropriately depending on whether the time zone is America/Los_Angeles or Asia/Hong_Kong.

The Oracle JET Cookbook includes implementations of the options discussed here. See Input Date and Time - Time Zone.

For more information about Oracle JET's IntlDateTimeConverter, see IntlDateTimeConverter.

Use Custom Converters in Oracle JET

You can create custom converters in Oracle JET by extending Converter. Custom converters can be used with Oracle JET components, provided they don't violate the integrity of the component. As with the built-in Oracle JET converters, you can also use them directly on the page.

The following image shows an implementation of a custom converter that converts the current date to a relative term. The Schedule For column uses a RelativeDateTimeConverter to convert the date that the page is run in the en-US locale to display Today, Tomorrow, and the date in two days.

To create and use a custom converter in Oracle JET:

  1. Define the custom converter.

    The Oracle JET Cookbook’s Custom Converter sample uses RelativeDateTimeConverter to wrap the Oracle JET IntlDateTimeConverter by providing a specialized format() method that turns dates close to the current date into relative terms for display. For example, in the en-US locale, the relative terms display Today, Yesterday, and Tomorrow. If a relative notation for the date value does not exist, then the date is formatted using the regular Oracle JET format() method supported by the Oracle JET IntlDateTimeConverter.

    For additional details about the IntlDateTimeConverter converter's supported methods, see the IntlDateTimeConverter API documentation.

  2. Add code to your app that uses the custom converter, as in the following example.

    The code sample below shows how you could add code to your script to use the custom converter.

    let rdConverter = new RelativeDateTimeConverter(relativeDayOptions);
  3. Add the Oracle JET element or elements that will use the custom converter to your page.

    The Oracle JET Cookbook includes implementations of the options discussed here. See Converters (Custom).

Use Oracle JET Converters Without Oracle JET Components

If you want to use a converter without binding it to an Oracle JET component, create the converter using the constructor for the converter of your choice.

The Oracle JET Cookbook includes a demo that shows how to use the number and date time converters directly in your pages without binding them to an Oracle JET component. In the demo image, the salary is a number formatted as currency, and the start date is an ISO string formatted as a date.

The viewModel defines a salaryConverter method to format a number as currency and a dateConverter that formats the start date using the date format style and medium date format while the view HTML binds to the returned values, as shown in the following snippet for Amy Flanagan’s salary and start date.

. . .
<p>Product Manager</p>
 <span style="white-space:nowrap;"><b>Salary</b>:
<span>
  <oj-bind-text value="[[amySalary]]"></oj-bind-text>
</span>
 </span>
 <br />
 <span style="white-space:nowrap;"><b>Joined</b>:
<span>
  <oj-bind-text value="[[amyStartDate]]"></oj-bind-text>
</span>
. . . 

The Oracle JET Cookbook includes implementations of the options discussed here. See Create Converter.

About Oracle JET Validators

Oracle JET validators provide properties that allow callers to customize the validator instance. The properties are documented as part of the validators’ API. Unlike converters where only one instance of a converter can be set on an element, you can associate one or more validators with an element.

When a user interacts with the element to change its value, the validators associated with the element run in order. When the value violates a validation rule, the value attribute is not populated, and the validator highlights the element with an error.

You can use the validators with an Oracle JET element or instantiate and use them directly on the page.

Use Oracle JET Validators with Oracle JET Components

Oracle JET editable elements, such as oj-input-text and oj-input-date, set up validators both implicitly, based on certain attributes they support such as required, min, max, and so on, and explicitly by providing a means to set up one or more validators using the component's validators attribute.

For example, the following code shows an oj-input-date element that uses the default validator supplied by the component implicitly. When the oj-input-date component reads the min and max attributes, it creates the implicit DateTimeRangeValidator.

<oj-form-layout id="validator-example">
  <oj-input-date
    id="dateTimeRange1"
    value="{{dateValue1}}"
    min="2000-01-01T08:00:00.000"
    help.instruction="enter a date that falls in the current 
                  millenium and not greater than today's date."
    max="[[todayIsoDate]]"
    label-hint="'min' attribute and 'max' option">
  </oj-input-date>
</oj-form-layout>

The script to create the view model for this example is shown below.

import * as ko from "knockout";
import * as ConverterUtilsI18n from "ojs/ojconverterutils-i18n";
import "ojs/ojknockout";
import "ojs/ojformlayout";
import "ojs/ojdatetimepicker";

class DemoViewModel {
 
  dateValue1: ko.Observable<string>;
  dateValue2: ko.Observable<string>;
  todayIsoDate: ko.Observable<string>;
  milleniumStartIsoDate: ko.Observable<string>;

constructor() {

  this.dateValue1 = ko.observable("");
  this.dateValue2 = ko.observable("");
  this.todayIsoDate = ko.observable(
    ConverterUtilsI18n.IntlConverterUtils.dateToLocalIso(new Date())
  );
  this.milleniumStartIsoDate = ko.observable(
    ConverterUtilsI18n.IntlConverterUtils.dateToLocalIso(new Date(2000, 0, 1))
    );
  } 
}

export = DemoViewModel;
define([
  "knockout",
  "ojs/ojconverterutils-i18n",
  "ojs/ojknockout",
  "ojs/ojdatetimepicker",
  "ojs/ojformlayout",
], function (
  ko,
  ConverterUtilsI18n
) {
  function DemoViewModel() {

  this.dateValue1 = ko.observable();
  this.dateValue2 = ko.observable();
  this.todayIsoDate = ko.observable(
   ConverterUtilsI18n.IntlConverterUtils.dateToLocalIso(new Date())
  );
  this.milleniumStartIsoDate = ko.observable(
   ConverterUtilsI18n.IntlConverterUtils.dateToLocalIso(new Date(2000, 0, 1))
  );
 }
  return DemoViewModel;
});

When the user runs the page, the oj-input-date element displays an input field with a calendar icon. The help.instruction attribute set on the element displays below the input field when you click on the input field. If you input data that is not within the expected range, the built-in validator displays an error message with the expected range.

The error thrown by the Oracle JET validator when validation fails is represented by the ValidatorError object, and the error message is represented by an object of type Message. The messages and hints that Oracle JET validators use when they throw an error are resources that are defined in the translation bundle included with Oracle JET. For more information about messaging in Oracle JET, see Work with User Assistance.

You can also specify the validator on the element's validators attribute, if it exists. The code sample below shows another oj-input-date element that calls a function which specifies the DateTimeRangeValidator validator (dateTimeRange) in the validators attribute.

<oj-form-layout id="validator-example">
 <oj-input-date
  id="dateTimeRange2"
  value="{{dateValue2}}"
  validators="[[validators]]"
  help.instruction="enter a date that falls in the current millenium and
                    not greater than today's date."
  label-hint="'dateTimeRange' type in 'validators' option">
 </oj-input-date>
</oj-form-layout>

The code below shows the additions to the viewModel with options that set the valid minimum and maximum dates and a hint that displays when the user sets the focus in the field.

import * as ko from "knockout";
import * as ConverterUtilsI18n from "ojs/ojconverterutils-i18n";
import AsyncDateTimeRangeValidator 
                = require("ojs/ojasyncvalidator-datetimerange");
import * as DateTimeConverter from "ojs/ojconverter-datetime";
import "ojs/ojknockout";
import "ojs/ojformlayout";
import "ojs/ojdatetimepicker";

class DemoViewModel {
  dateValue1: ko.Observable<string>;
  dateValue2: ko.Observable<string>;
  todayIsoDate: ko.Observable<string>;
  milleniumStartIsoDate: ko.Observable<string>;
  validators: ko.Computed<AsyncDateTimeRangeValidator<string>[]>;

  constructor() {
    this.dateValue1 = ko.observable("");
    this.dateValue2 = ko.observable("");
    this.todayIsoDate = ko.observable(
      ConverterUtilsI18n.IntlConverterUtils.dateToLocalIso(new Date())
    );
    this.milleniumStartIsoDate = ko.observable(
    ConverterUtilsI18n.IntlConverterUtils.
                   dateToLocalIso(new Date(2000, 0, 1))
    );

    this.validators = ko.computed(() => {
      return [
        new AsyncDateTimeRangeValidator({
          max: this.todayIsoDate(),
          min: this.milleniumStartIsoDate(),
          hint: {
            inRange: "Enter a date that falls in the 
                      current millennium.",
          },
          converter: new DateTimeConverter.IntlDateTimeConverter({
            day: "2-digit",
            month: "2-digit",
            year: "2-digit",
          }),
        }),
      ];
    });
  } 
}

export = DemoViewModel;
define([
  "knockout",
  "ojs/ojconverterutils-i18n",
  "ojs/ojasyncvalidator-datetimerange",
  "ojs/ojconverter-datetime",
  "ojs/ojknockout",
  "ojs/ojdatetimepicker",
  "ojs/ojformlayout",
], function (
  ko,
  ConverterUtilsI18n,
  AsyncDateTimeRangeValidator,
  DateTimeConverter
) {
  function DemoViewModel() {
    
    this.dateValue1 = ko.observable();
    this.dateValue2 = ko.observable();
    this.todayIsoDate = ko.observable(
      ConverterUtilsI18n.IntlConverterUtils.
                      dateToLocalIso(new Date())
    );
    this.milleniumStartIsoDate = ko.observable(
      ConverterUtilsI18n.IntlConverterUtils.
             dateToLocalIso(new Date(2000, 0, 1))
    );

    this.validators = ko.computed(
      function () {
        return [
          new AsyncDateTimeRangeValidator({
            max: this.todayIsoDate(),
            min: this.milleniumStartIsoDate(),
            hint: {
              inRange: "Enter a date that falls 
                        in the current millennium.",
            },
            converter: new DateTimeConverter.
                              IntlDateTimeConverter({
              day: "2-digit",
              month: "2-digit",
              year: "2-digit",
            }),
          }),
        ];
      }.bind(this)
    );
  }

  return DemoViewModel;
});

When the user runs the page for the en-US locale, the oj-input-date element displays an input field that expects the user's input date to be between 01/01/2000 and the current date. When entering a date value into the field, the date converter accepts alternate input as long as it can parse it unambiguously. This offers end users a great deal of leniency when entering date values. For example, typing 1-2-3 converts to a Date that falls on the 2nd day of January, 2003. If the Date value also happens to fall in the expected Date range set in the validator, then the value is accepted. If validation fails, the component displays an error.

Oracle JET elements can also use a regExp validator. If the regular expression pattern requires a backslash, while specifying the expression within an Oracle JET element, you need to use double backslashes. The options that each validator accepts are specified in API Reference for Oracle® JavaScript Extension Toolkit (Oracle JET).

The Oracle JET Cookbook contains the complete example discussed in this section as well as examples that show the built-in validators for date restrictions, length, number range, regular expression, and required fields. For details, see Validators.

For more information about Oracle JET component validation, see Understand How Validation and Messaging Works in Oracle JET Editable Components.

Use Custom Validators in Oracle JET

You can create custom validators in Oracle JET that you can reference like built-in validators from the validators attribute.

The following image shows a custom validator that displays an error message if the user’s password doesn’t match.

To create and use a custom validator:

  1. Define the custom validator.

    The Oracle JET Cookbook sample defines an equalToPassword custom validator of type Validator. Because the custom validator provides the methods expected of a Validator instance, Oracle JET accepts it.

  2. Add code to your app that uses the custom validator.

    The code sample below shows how you could add code to your view page to use the custom validator. In this example, both input fields are defined as oj-c-input-password elements. The first instance validates that the user entered a password that meets the app's password requirements. The second instance uses the equalToPassword validator to verify that the password in the second field is equal to the password entered in the first field.

    <oj-form-layout id="custom-validator-example">
      <oj-c-input-password
        id="password"
        required
        value="{{password}}"
        validators="[[validators]]"
        label-hint="Password"
        mask-icon="visible"></oj-c-input-password>
      <oj-c-input-password
        id="cpassword"
        value="{{passwordRepeat}}"
        validators="[[[equalToPassword]]]"
        label-hint="Confirm Password"
        mask-icon="visible"></oj-c-input-password>
    </oj-form-layout>

    The Oracle JET Cookbook contains the complete code sample discussed in this section. See Validators (Custom).

About Asynchronous Validators

Oracle JET input components support asynchronous server-side validation via the validators attribute. That means you can check input values against server data without the need to submit a form or refresh a page.

Two example scenarios illustrate where you can use asynchronous server-side validation:

  • In a form that collects new user data, you validate input in an email field to check if the input value has been registered previously.
  • Set number range validators that check against volatile data. For example, on an e-commerce website, you can check the user’s cart against the available inventory and inform the user if the goods are unavailable without them submitting the cart for checkout.

The Oracle JET Cookbook has a sample that uses the validators attribute and dummy data to simulate server-side validation.

The following code shows an oj-input-text element with the validators attribute set to validators and asyncValidator observables in the viewModel code. The validators attribute must be of type AsyncValidator to fulfill the API contract required to create the asynchronous validator.

<oj-form-layout id="fl1">
  <oj-c-input-text
    id="input-text"
    required
    label-hint="Quantity Limit"
    on-valid-changed="[[validChangedListener]]"
    validators="[[[validators, asyncValidator]]]"
    value="{{quantityLimit}}"
    converter="[[currencyConverter]]">
  </oj-c-input-text>
</oj-form-layout>

The viewModel code includes a number range validator created in the asyncValidator object that returns a Promise. A Promise object represents a value that may not be available yet, but will be resolved at some point in the future. In asynchronous validation, the AsyncValidator.validate() function returns a Promise that evaluates to Boolean true if validation passes and if validation fails, it returns an Error. For more information, see the validators attribute section of Input Text or see Promise (MDN).

The Oracle JET Cookbook includes implementations of the options discussed here. See Async Validators.