2

I've created a knockoutjs application using AMD. Currently I'm kinda stuck with validation. Here's the ViewModel code:

define(['knockout', 'hasher', 'text!./login-window.html'],
    function (ko, hasher, templateMarkup) {
    'use strict';

    function LoginWindowViewModel(params) {
        //observables
        this.properties = ko.validatedObservable({
            username: ko.observable().extend({
                required: { message: 'Please supply your user name' }
            }),
            password: ko.observable().extend({
                required: { message: 'Please supply your password' }
            })
        });
    }

    return { viewModel: LoginWindowViewModel, template: templateMarkup };

});

<div data-bind="css: { 'form-group': true, 'has-error': !properties().username.isValid() }">
    <label for="input-username" class="col-lg-3 control-label">Username</label>
    <div class="col-lg-9">
        <input type="text" name="input-username" class="form-control" data-bind="value: properties().username" />
    </div>
</div>
<div data-bind="css: { 'form-group': true, 'has-error': !properties().password.isValid() }">
    <label for="input-password" class="col-lg-3 control-label">Password</label>
    <div class="col-lg-9">
        <input type="text" name="input-password" class="form-control" data-bind="value: properties().password" />
    </div>
</div>

The problem is that on page load knockout adds has-errors class to the "wrapper divs" (those with form-group class). How can I turn on validation after user typed something into bound input?

Before you point me here: Knockout Validation evaluates immediately on load - I don't have a problem with a validation message showing up, but with div being added a class it shouldn't have at that moment.

Community
  • 1
  • 1
Marek M.
  • 3,799
  • 9
  • 43
  • 93

2 Answers2

1

Try this on the binding:

css: { 'form-group': true, 'has-error': !properties().username.isValid() && properties().username.isModified() }

Basically we are checking if observable has been modified to present the error. isModified is an observable that is inserted automatically by ko validation.

If something in your view model is actually setting the observable to empty or null, (some initialisation code for example) you then need to:

properties().username.isModified(false)

I Haven't tested it so it might need some tweaking

Luis
  • 5,979
  • 2
  • 31
  • 51
-1

I figured out a temporary solution, but I don't like it, so anybody with a better idea - please come forward :).

this.shouldValidateUsername = ko.pureComputed(function () {
    return !this.properties().username.isValid() && this.validationIsOn();
}, this);
this.shouldValidatePassword = ko.pureComputed(function () {
    return !this.properties().password.isValid() && this.validationIsOn();
}, this);

and the interesting part of html is:

<div data-bind="css: { 'form-group': true, 'has-error': shouldValidateUsername() }">(...)

I'm switching the validationIsOn observable thus turning the validation on and off.

Marek M.
  • 3,799
  • 9
  • 43
  • 93
  • If you just want to influence the display, how about this: Add a `css: {showValidation: hasBeenSubmitted}` binding to your form. Once the form is submitted for the first time, set the `hasBeenSubmitted` observable to true. Define your CSS like this `.showValidation .has-error { ... }`. That way `.has-error` has no effect at page load. You wouldn't have to add any custom logic and only one additional observable on the main view model. Of course you could implement a `hasBeenModified` observable instead of `hasBeenSubmitted`, for example. – Tomalak May 09 '15 at 13:15