JSFiddle - React, Tailwind, and code Playground

by bombo

HTML

<div>
    viewModel.observable:
    <input type="text" data-bind="value: observable" />
    <button data-bind="click: function () { observable.valueHasMutated(); }">notify</button>
</div>

<div>
    viewModel.observableArray:
    <ul data-bind="foreach: observableArray">
        <li>
            <!-- ko text: name --><!-- /ko -->:
            <input type="text" data-bind="value: entryProp" />
            <button data-bind="click: function () { entryProp.valueHasMutated(); }">notify</button>
        </li>
    </ul>
    <button data-bind="click: function () { observableArray.push({ name: 'entry' + arrayCount, entryProp: ko.observable('' + arrayCount) }); arrayCount = arrayCount + 1; }">add</button>
</div>

<div>
    flag is true:
    <input type="checkbox" data-bind="checked: flag" />
</div>

<hr />

<div>
    computed1: <!-- ko text: computed1 --><!-- /ko --> -
    evaluation count: <!-- ko text: computed1Count --><!-- /ko --><br />
    
    computed2: <!-- ko text: computed2 --><!-- /ko --> -
    evaluation count: <!-- ko text: computed2Count --><!-- /ko --><br />
    
    computed3: <!-- ko text: computed3 --><!-- /ko --> -
    evaluation count: <!-- ko text: computed3Count --><!-- /ko --><br />
    
    computed4: <!-- ko text: computed4 --><!-- /ko --> -
    evaluation count: <!-- ko text: computed4Count --><!-- /ko -->
</div>

CSS

div {
    margin: 5px;
    background: #ddd;
    padding: 5px;
    border: 1px solid black;
}

JavaScript

var viewModel = {
        observable: ko.observable('main'),
        observableArray: ko.observableArray(),
        flag: ko.observable(false)
    };

viewModel.observableArray.push({
    name: 'entry1',
    entryProp: ko.observable('1')
});

viewModel.observableArray.push({
    name: 'entry2',
    entryProp: ko.observable('2')
});

//-------------------------------------------------------------------------//

viewModel.computed1 = ko.computed(function () {
    logEvaluation('computed1');
    return viewModel.observable();
});

viewModel.computed2 = ko.computed(function () {
    logEvaluation('computed2');
    if (!viewModel.flag()) {
        return 'no';
    } else {
        return viewModel.observable();
    }
});

viewModel.computed3 = ko.computed(function () {
    var i, j,
        array = viewModel.observableArray();
    logEvaluation('computed3');
    for (i = 0, j = array.length; i < j; i++) {
        if (array[i].entryProp() === '1') {
            return 'got it';
        }
    }
});

viewModel.computed4 = ko.computed(function () {
    var array = viewModel.observableArray();
    logEvaluation('computed4');
    return concatenate(array);
});

//-------------------------------------------------------------------------//

function concatenate(array) {
    var i, j,
        result = '';
    for (i = 0, j = array.length; i < j; i++) {
        result = result + array[i].entryProp();
    }
    return result;
}
    
//-------------------------------------------------------------------------//




viewModel.computed1Count = ko.observable(1);
viewModel.computed2Count = ko.observable(1);
viewModel.computed3Count = ko.observable(1);
viewModel.computed4Count = ko.observable(1);

function logEvaluation(name) {
    var count = viewModel[name + 'Count'];
    if ('console' in window) {
        console.log(name + ' evaluated');
    }
    if (typeof count === 'function') {
        count(count() + 1);
    }
}

viewModel.arrayCount = 3;

ko.applyBindings(viewModel);