Knockout ViewModel Mappings (Album w/ Tracks)

by KodeKreachor

HTML

<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.js"></script>
<script src="https://raw.github.com/SteveSanderson/knockout.mapping/master/build/output/knockout.mapping-latest.debug.js"></script>
<script id="albumTemplate" type="text/html">
    <div class="album">
        <div class="albumData">Album:</div>
        <div class="albumData" data-bind="text:name"></div><br />
        <div class="albumData">Tracks:</div><br />
        <div data-bind="template:{name:'trackTemplate',foreach:tracks}"></div>
    </div>
</script>

<script id="trackTemplate" type="text/html">
    <div class="track">
    <div class="trackData" data-bind="text:title"></div>
    <div class="trackData" data-bind="text:file_name"></div>
    <div class="trackData" data-bind="text:price"></div>
    </div>
</script>

<div class="albums">
    <div data-bind="template:{name:'albumTemplate',foreach:albums}"></div>
</div>

CSS

.albums{}
.albumData{float:left; margin-left:10px; font-weight:bold;}
.trackData{float:left; margin-left:10px;}
.album{display:block; margin-top:20px;}
.track{display:table;}

JavaScript

var Album = function(data){
        this.id = ko.observable(data && data.id);
        this.name = ko.observable(data && data.name);
        this.tracks = ko.observableArray();
        ko.mapping.fromJS(data, mapping, this);
    }
        
    var Track = function (data) {
      this.id = ko.observable(data.id);
      this.title = ko.observable(data.title);
      this.file_name = ko.observable(data.file_name);
      this.thumb = ko.observable(data.thumb);
      this.price = ko.observable(data.price);
      ko.mapping.fromJS(data, mapping, this);
    };

    var viewModel = function(){
        var self = this;
        this.albums = ko.observableArray([new Album()]); 
        this.init = function(data){
            console.log(data)
            var obj_albums = [];
            $.each(data.albums, function (index, album) {
                obj_albums.push(new Album(album));
            });           
            self.albums.removeAll();
            self.albums.push.apply(self.albums, obj_albums);
            self.albums.valueHasMutated();
        }          
    }
    
    var mapping = {
        'albums': { create: function(options) { return new Album(options.data); } },
        'tracks': { create: function(options) { return new Track(options.data); } }
    };    

var albumData = {albums:[{id:1,name:'10,000 Days',tracks:[
                     {id:1,title:'Vicarious',file_name:'v.mp3',thumb:'',price:'$0.99'},
                     {id:2,title:'Jambi',file_name:'j.mp3',thumb:'',price:'$0.99'},
                     {id:3,title:'Wings for Marie (Pt 1)',file_name:'w.mp3',thumb:'',price:'$0.99'}]},
                        
                        {id:2,name:'Lateralus',tracks:[
                     {id:1,title:'Parabola',file_name:'p.mp3',thumb:'',price:'$0.99'},
                     {id:2,title:'Eon Blue Apocalypse',file_name:'e.mp3',thumb:'',price:'$0.99'},
                     {id:3,title:'Triad',file_name:'t.mp3',thumb:'',price:'$0.99'}]}]};

$(function(){
    var vm =...