Thursday, March 17, 2016

Sort-of Validation Messages -- How to use Oracle JET Custom Messages

Let's say you have a required field on a form and a user doesn't enter anything into that field. That empty field deserves a validation error message. Oracle JET's built-in validation handles this scenario quite nicely. Let's consider another scenario: A user enters an invalid user name and password. Is this a validation issue or some other type of error? Could you write an Oracle JET validator for credentials validation? One of the key differences between the required validation and a credentials validation is the asynchronous data-driven nature of credentials validation. Validating credentials likely requires an Ajax request. What do you do while waiting for a response? Can you write a validator that waits for an Ajax response before returning true/false (Yes, but technically it would be a blocking SJax (synchronous) request and nobody likes blocking synchronous requests)? Does it even matter?

I am a fan of Oracle JET's inline messages. When writing the failure logic for a login page, my first question is, "How can I reuse those cool inline Oracle JET messages to tell the user that authentication failed?" I can't exactly write an authentication validator because of the asynchronous nature of credential validation. On form submit, I won't know if the credentials are valid until I receive a response. By that time, validation is over. An alternative is to notify the user through Oracle JET's inline messages. Keeping with the authentication example, let's say you have an ojInputPassword component and you want to display an error message under the password (inline) when authentication fails. To that ojInputPassword element, add a messagesCustom attribute and bind it to an observable. For example:

<input id="password" name="password" data-bind="ojComponent: {
    component: 'ojInputPassword', value: password,
    messagesCustom: authenticationMessages,
    invalidComponentTracker: $component.tracker}" type="password"
    required />

In your ViewModel you will have a corresponding observable definition for authenticationMessages like so:

self.authenticationMessages = ko.observableArray([]);

Then when that Ajax authentication request returns a failure, you can insert an object into that authenticationMessages observable like this:

self.authenticationMessages.push({
  summary: "Authentication failed",
  detail: "Invalid user ID or password",
  severity: oj.Message.SEVERITY_TYPE.ERROR
});

The invalidShown field of our oj.invalidComponentTracker (named tracker, see Validating Oracle JET Input Before Submission Take II) will now return true (tracker.invalidShown === true). Here is a sample showing the inline error message as well as the tracker object and authenticationMessages array.

So now our user knows that his or her credentials are invalid and can enter some new credentials. What about that visible error message? Since we didn't use a custom validator to display the message, it isn't going to disappear based on user input. Rather, we need to control the presence (or absence) of that error message. It is my thought that once the user changes the user ID or password, that error message should disappear and only reappear if the new credentials are invalid. I see two ways to make this happen:

  1. Bind an event handler to the change event of both the user ID and password fields
  2. Subscribe to the user ID and Password observables

Either is acceptable, but I prefer the subscription route. Here is what that might look like:

var resetAuthenticationFailure = function() {
  self.authenticationMessages.removeAll();
};

self.userid.subscribe(resetAuthenticationFailure);
self.password.subscribe(resetAuthenticationFailure);

In the code sample above (above the image), do you see the severity attribute of the new message object? The messagesCustom isn't just for error messages. Done right, you can use it for information and confirmation messages as well. To see a "kitchen sink" example of messagesCustom, visit the Help, Hints and Messaging: Inline Multiple Messages recipe of the Oracle JET Cookbook.

No comments:

Post a Comment