JSFiddle - React, Tailwind, and code Playground

by sukobuto

HTML

<h1>KnocoutJS ViewModel Modified Notification</h1>

<input type="text" placeholder="First name" data-bind="value: first_name, valueUpdate: 'afterkeydown'"/>
<input type="text" placeholder="Last name" data-bind="value: last_name, valueUpdate: 'afterkeydown'"/>
<input type="number" placeholder="Age" data-bind="value: age, valueUpdate: 'afterkeydown'"/>

<br/>
<span data-bind="visible: modified">MODIFIED 
    <span data-bind="text: modified"></span> times.
</span>

JavaScript

function ViewModel(data) {
    self.first_name = ko.observable("");
    self.last_name = ko.observable("");
    self.age = ko.observable();
    var field_names = [ 'first_name', 'last_name', 'age' ];
    
    self.setData = function(data) {
        for (var i in field_names) {
            var key = field_names[i];
            if (data.hasOwnProperty(key)) self[key](data[key]);
        }
    }
    
    if (data) self.setData(data);
    // define modified property
    self.modified = modifiedEvaluator(self, field_names);
}

function modifiedEvaluator(view_model, field_names) {
    var subscribables = [];
    var oldValues = [];
    var modified_count = 0;
    for (var i in field_names) {
        var key = field_names[i];
        if (view_model.hasOwnProperty(key) && ko.isSubscribable(view_model[key])) {
            subscribables.push(view_model[key]);
            oldValues.push(view_model[key]())
        }
    }
    return ko.computed(function() {
        var modified = false;
        for (var i = 0; i < subscribables.length; i++) {
            if (oldValues[i] !== subscribables[i]()) modified = true;
        }
        return modified ? ++modified_count : false;
    });
}

ko.applyBindings(new ViewModel({
    first_name: 'Kenta',
    last_name: 'Suzuki',
    age: 24
}));