JSFiddle - React, Tailwind, and code Playground

by tanya_22

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.2/knockout.validation.min.js"></script>
<script id="customMessageTemplate" type="text/html"><!--
    --><em class="customMessage" data-bind="validationMessage: field"></em>
</script>
                                    
<fieldset>
    <legend class="well">
        User: <strong data-bind="text: errors().length"></strong> errors
    </legend>
    
    <div class="row">
        <label>First name:</label>
        <input type="text" data-bind="textInput: firstName"/>
    </div>
    
    <div class="row">
        <label>Last name:</label>
        <input data-bind="value: lastName"/>
    </div>
    
    <div class="row" data-bind="validationOptions: { messageTemplate: 'customMessageTemplate' }">
        <div class="row">
            <label>Email:</label>
            <input data-bind="value: emailAddress" required="required" pattern="@"/>
        </div>
        <div class="row">
            <label>Location:</label>
            <input data-bind="value: location"/>
        </div>
        <div class="row">
            <label>Age:</label>
            <input data-bind="value: age" required="required"/>
        </div>
    </div>
        
    <div class="row">
        <label>Subscriptions:</label>
        <select data-bind="value: subscription, options: subscriptionOptions, optionsCaption: 'Choose one...'"></select>
    </div>

    <div class="row">
        <label>Password:</label>
        <input data-bind="value: password" type="password"/>
    </div>
    
    <div class="row">
        <label>Retype password:</label>
        <input data-bind="value: confirmPassword" type="password"/>
    </div>
    
    <div class="row">
        <label>10 + 1 = </label>
        <input data-bind='value: captcha'/>
    </div>
</fieldset>

<fieldset>
    <button type="button" data-bind='click: submit'>Submit</button>
    &nbsp;
...

CSS

.validationMessage {
    color: #f00;
}
.customMessage {
    color: #FFA500;
}

/*-----------------------------------------------------------------*/
@import url(https://fonts.googleapis.com/css?family=Open+Sans:700,400);
body {padding: 10px 0;font-family: 'Open Sans', sans-serif;font-weight: 400;font-size: 14px;}
fieldset {padding: 10px;}
strong {font-weight: 700;}
label {display:inline-block;width: 120px;}
button {padding: 3px 6px;}
input, select {width: 180px; padding: 3px 6px; border-radius: 3px;border: 1px solid #ccc;outline: none;margin-right: 5px;transition: .3s all ease-in-out;}
select {width:194px;}
input:focus {border: 1px solid #5579A9;box-shadow: 0px 0px 4px 0px #6FA5ED;}
.row {margin-bottom: 5px;}
.well {border:1px solid #ccc;border-radius: 3px;background-color:#efefef;box-sizing:border-box; width:100%;padding:10px;}

JavaScript

ko.validation.rules.pattern.message = 'Invalid.';

ko.validation.init({
    registerExtenders: true,
    messagesOnModified: true,
    insertMessages: true,
    parseInputAttributes: true,
    messageTemplate: null
}, true);


var captcha = function(val) {
    return val == 11;
};

var mustEqual = function(val, other) {
    return val == other;
};

var viewModel = {
    firstName: ko.observable().extend({
    	required: true,
      pattern: {
        message: 'Hey it is my pattern',
        params: '^[A-Z].$'
      },
    }),
    lastName: ko.observable().extend({required: true}),
    emailAddress: ko.observable().extend({
        // custom message
        required: {
            message: 'Please supply your email address.'
        }
    }),
    age: ko.observable().extend({min: 1, max: 100}),
    location: ko.observable(),
    subscriptionOptions: ['Technology', 'Music'],
    subscription: ko.observable().extend({required: true}),
    password: ko.observable(),
    captcha: ko.observable().extend({
        // custom validator
        validation: {
            validator: captcha,
            message: 'Please check.'
        }
    }),
    submit: function() {
        if (viewModel.errors().length === 0) {
            alert('Thank you.');
        }
        else {
            alert('Please check your submission.');
            viewModel.errors.showAllMessages();
        }
    },
    reset: function() {
        Object.keys(viewModel).forEach(function(name) {
            if (ko.isWritableObservable(viewModel[name])) {
                viewModel[name](undefined);
            }
        });
        if (ko.validation.utils.isValidatable(viewModel.location)) {
            viewModel.location.rules.removeAll();
        }
        viewModel.errors.showAllMessages(false);
    }
};

viewModel.confirmPassword = ko.observable().extend({
    validation: {
        validator: mustEqual,
        message: 'Passwords do not match.',
        params: viewModel.password
   ...