knockoutのscope(context)

Knockout Advent Calendar 2015

by MKGaru

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-debug.js"></script>
<script src="https://mbest.github.io/knockout.punches/knockout.punches.js"></script>
<script src="https://rawgit.com/SteveSanderson/knockout-es5/master/dist/knockout-es5.js"></script>
<div data-bind="foreach:countries">
    <div class="country">
        <span>{{name}}</span>
        {{#foreach: states}}
        <div class="state">
            <span>{{name}}</span>
            {{#foreach: cities}}
            <div class="city">
                <span>{{name}}</span>は、{{$parents[1].name}}の{{$parents[0].name}}にあります
            </div>
            {{/foreach}}
        </div>
        {{/foreach}}
    </div>
</div>

CSS

.country{
    border:solid 1px green;
    margin-bottom: 1em;
}
.state{
    border:solid 1px blue;
    margin-left: 1em;
}
.city{
    border:solid 1px orange;
    margin-left: 1em;
}

JavaScript

function Country(name){
    this.states=[];
    this.name = name;
    ko.track(this);
}
function State(name){
    this.cities=[];
    this.name = name;
    ko.track(this);
}
function City(name){
    this.name = name;
    ko.track(this);
}

function VM(){
    var countries = this.countries = [];
	var src = [
        {
            name:'jp',
            state:[
                {name:'東京',city:[{name:'千代田'},{name:'港'},{name:' 渋谷'}]},
                {name:'大阪',city:[{name:'大阪'},{name:'堺'},{name:'松原'}]},
                {name:'宮城',city:[{name:'仙台'},{name:'角田'},{name:'名取'}]}
            ]
        },
        {
            name:'us',
            state:[
                {name:'Texas',city:[{name:'SanAntonio'},{name:'Austin'},{name:' Huston'}]},
                {name:'NewYork',city:[{name:'Rochester'},{name:'Buffalo'}]}
            ]
        }
    ];
    // mapping to model
    src.forEach(function(c){
        var country = new Country(c.name);
        c.state.forEach(function(s){
            var state = new State(s.name);
            s.city.forEach(function(ci){
            	state.cities.push(new City(ci.name));
        	});
            country.states.push(state)
        });
        countries.push(country);
    });
    ko.track(this);
}
var vm = new VM();

ko.punches.enableAll();
ko.applyBindings(vm);