JSFiddle - React, Tailwind, and code Playground

by mgrcic

HTML

<label>Username<br />
    <input type="text" class="full-width" data-bind="value: userName" />
    <span class="error" data-bind="visible: userName.displayRequiredError, text: userName.requiredValidationMessage"></span>
</label>
<br/>
<label>Password<br />
    <input type="password" class="full-width" data-bind="value: password"/>
    <span class="error" data-bind="visible: password.displayRequiredError, text: password.requiredValidationMessage"></span>
</label>
<br/><br/>
<button data-bind="click: login">Log in</button>

CSS

.error { color:red }

JavaScript

ko.extenders.validation = function(target, modelValidationContainer) {
    // array of all rules for the given observable
    target.rules = [];

    // check the observable against all attached validators
    target.isValid = function() {
        var validSoFar = true;
        var i = 0;
        while (i < target.rules.length) {
            if (!target.rules[i]()) {
                validSoFar = false;
            }
            i += 1;
        }
        return validSoFar;
    };

    // push valid checking function to the model
    modelValidationContainer.push(target.isValid);

    return target;
}
ko.extenders.requiredValidation = function(target, validationMessage) {

    // subobservables that can be bound to HTML elements
    target.displayRequiredError = ko.observable(false);
    target.requiredValidationMessage = ko.observable();

    // The actual validation logic
    var validate = function() {
        if (target() == null || target() == '') {
            target.displayRequiredError(true);
            target.requiredValidationMessage(validationMessage ? validationMessage : "This field is required.");
            return false;
        }
        else {
            target.displayRequiredError(false);
            return true;
        }
    };

    // Add it to our validation rules container
    target.rules.push(validate);

    // Everytime the observable change, validate it
    target.subscribe(validate);

    return target;
}


var BaseModel = function() {
    var self = this;

    this.validationContainers = [];

    // Iterate through the validationContainers of all
    // the observables with validation rules and check
    // validity
    this.isValid = function() {
        var validSoFar = true;
        var i = 0;
        while (i < self.validationContainers.length) {
            if (!self.validationContainers[i]()) {
                validSoFar = false;
            }
            i += 1;
        }
        return validSoFar;
    };
};

var login =...