Knockoutjs.com - Cart editor example

http://knockoutjs.com/examples/cartEditor.html

by alansouzati

HTML

<script src="http://knockoutjs.com/examples/resources/sampleProductCategories.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.0.0.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout-validation/1.0.2/knockout.validation.min.js"></script>
<div class="field" data-bind="visible: activeErrors().length > 0">
    You have <span data-bind="text: activeErrors().length"></span> errors on your form! 
</div>    

<div class="field">
    <p class="validationMessage" data-bind="errorMessageDisplay: firstName"></p> 
   First Name: <input type="text" data-bind="value: firstName, valueUpdate: 'afterkeydown', event : { change: validate.bind($data, firstName)}" class="textBox"/> 
</div>
<div class="field">    
    <p class="validationMessage" data-bind="errorMessageDisplay: lastName"></p>  
   Last Name: <input type="text" data-bind="value: lastName, valueUpdate: 'afterkeydown', event : { change: validate.bind($data, lastName)}" class="textBox"/> 
</div>
<div class="field"> 
   Age:  <input type="text" data-bind="value: age" class="textBox"/> 
</div>    
<div class="button"> 
    <input type="button" data-bind="click: save, enable: errors().length === 0" value="Save" />
</div>

CSS

div.field {
    padding: 5px;
}

div.field .textBox{
    height: 20px;
}

div.button {
    padding: 5px;
}

JavaScript

ko.bindingHandlers.errorMessageDisplay = {
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var value = valueAccessor();
        var jQueryElement = $(element);
        
        if (viewModel.activeErrors().length > 0 && ko.validation.utils.isValidatable(value) && value.isModified() && !(value.isValid())) {
            jQueryElement.text(viewModel.getErrorField(value).error);
            jQueryElement.show();
        } else {
            jQueryElement.hide();
        }
    }
}

ko.validation.init({
		decorateElement: true,  // will add the css class 'validationElement' to the field with error
		errorsAsTitle: false,   // will not add 'title' attribute
		messageOnModified: false,   // displaying of error message is handled separately
		insertMessages: false   // displaying of error message is handled separately
	}, true);

var Person = function() {
    var self = this;
    self.firstName = ko.observable().extend({ required: true, minLength: 3 });
    
    self.lastName = ko.observable().extend({ required: true });;
    self.age = ko.observable();
    
    self.save = function () {
        alert('Save!');
    }
    
    //validation related code
    self.activeErrors = ko.observable([]);
    
    self.activeErrors.add = function(field) {
        var existingField = false;
        $.each(self.activeErrors(), function(index, currentField) {
            if(currentField === field) {
                existingField = true;
                return false;
            }
        });
        
        if(!existingField) {
            var array = self.activeErrors();
            array.push(field);
            self.activeErrors(array);
        }
    }
    
    self.activeErrors.remove = function(field) {
        var activeFields = $.grep(self.activeErrors(), function(currentField) {
            return currentField !== field;
        });
        
        self.activeErrors(activeFields);
    }
    
    self.getErrorField =...