JSFiddle - React, Tailwind, and code Playground

by gurkavcu

HTML

<script src="http://knockoutjs.com/js/jquery.tmpl.js"></script>
<script src="http://knockoutjs.com/js/knockout-1.2.1.js"></script>
Region: <select data-bind="options: allowedRegions, optionsText: 'name', optionsValue: 'code', value: chosenRegion"></select>
Show: <select data-bind="options: [10, 20, 50, 500], value: numberToShow"></select> record(s)

&nbsp;<i data-bind="visible: fetchedData.inProgress"><b>Loading...</b></i>

<hr/>
<table>
    <thead><tr><th><b>Name</b></th><th><b>Capital</b></th><th><b>Code</b></th></tr></thead>
    <tbody data-bind="template: { name: 'countryTemplate', foreach: fetchedData }"></tbody>
</table>
<script id="countryTemplate" type="text/html">
    <tr>
        <td>${ name }</td>
        <td>${ capitalCity }</td>
        <td>${ iso2Code }</td>
    </tr>
</script>

JavaScript

function asyncDependentObservable(evaluator, owner) {
    var result = ko.observable(), currentDeferred;
    result.inProgress = ko.observable(false); // Track whether we're waiting for a result
    
    ko.dependentObservable(function() {
        // Abort any in-flight evaluation to ensure we only notify with the latest value
        if (currentDeferred) { currentDeferred.reject(); }
        
        var evaluatorResult = evaluator.call(owner);
        // Cope with both asynchronous and synchronous values
        if (evaluatorResult && (typeof evaluatorResult.done == "function")) { // Async
            result.inProgress(true);
            currentDeferred = $.Deferred().done(function(data) {
                result.inProgress(false);
                result(data);
            });
            evaluatorResult.done(currentDeferred.resolve);
        } else // Sync
            result(evaluatorResult);
    });
    
    return result;
}

function myViewModel() {
    this.allowedRegions = [{name:"World", code:"WLD"}, { name:"Europe / Asia", code:"ECS"}, {name:"North America", code:"NAC"}];
    this.chosenRegion = ko.observable("WLD");
    this.numberToShow = ko.observable(10);
    
    this.fetchedData = asyncDependentObservable(function() {
        return $.ajax("http://api.worldbank.org/country?prefix=?", {
            dataType: "jsonp",
            data: { per_page: this.numberToShow, region: this.chosenRegion, format: "jsonp" }
        }).pipe(function(data) { return data[1] });
    }, this);
}

ko.applyBindings(new myViewModel());