View Live Demo
var Tile = function (title, description, color) { var self = this; self.title = ko.observable(title); self.description = ko.observable(description); self.tileColor = ko.observable(color); self.editPanel = ko.observable(false); self.expandEdit = function () { self.editPanel(true); }; self.collapseEdit = function () { self.editPanel(false); }; };
Another additional observable is taken named editPanel which will detect visibility of its tile’s edit panel. expandEdit and collapsEdit will make editPanel true or false on click event. Here ObservableArray is taken to store all tiles. addTile and removeTile functions will add new tile on the view and remove tile will delete its corresponding tile from the view and from the observableArray as well.
var TileModel = function () { var self = this; self.lines = ko.observableArray([ new Tile("Batman", "The Dark Night Rises", "#525252"), new Tile("Transformer", "Revenge of the Fallen", "#DA532C") ]); self.addTile = function () { self.lines.push(new Tile("Title", "Description", RandomColor())) }; self.removeTile = function (line) { self.lines.remove(line) }; }; ko.applyBindings(new TileModel());
Also two tiles are pushed into the array on load and observable will bind them with the HTML control automatically. Then finally we’ve bind the full model with Knockout with ko.applyBindings().
<a id="aCreate" class="btn-add-tile" data-bind='click: addTile'>Add Tile</a> <div class="tile-container" data-bind='foreach: lines'> <div class="tile-area"> <div class="tile-elem" data-bind="style: { background: tileColor }"> <p class="tile-description" data-bind="text: description"></p> </div> <span class="tile-title" data-bind="text: title" style=""></span> <div class="bottom-bar"> <span class="arrow" data-bind='click: expandEdit, ifnot:editPanel'> <img src="Styles/images/MetroDown.png" alt="Open edit panel" /></span> <span class="arrow" data-bind='click: collapseEdit, if:editPanel'> <img src="Styles/images/MetroUp.png" alt="Close edit panel" /></span> <span class="close-btn" data-bind='click: $parent.removeTile'> <img src="Styles/images/MetroClose.png" alt="Remove tile" /></span> </div> <div data-bind="if: editPanel"> <div class="edit-panel"> <label>Title:</label> <input class="text-title" data-bind="value: title, valueUpdate: 'afterkeydown'" maxlength="12" /> <label>Description:</label> <textarea class="txtdesc" rows="2" data-bind="value: description, valueUpdate: 'afterkeydown'"></textarea> </div> </div> </div> </div>
Here Knockout will search for data-bind attribute to bind data with its model. Now on clicking Add Tile button we are calling addTile function from TileModel which adds a new object to lines. With foreach, Knockout is generating all the tile object stored in lines with a loop. Every time a tile is added or removed, it tracks the changes in the model and bind tiles dynamically. Now edit panel’s <textarea> is bind with <p> of tile element with description object. <p> is updated when <textarea> has an input character. We are updating the description object after key down. Title will update same way like description. So the main thing is all the observables track dependencies among the HTML controls and it updates automatically.
Knockout follows MVVM pattern where observable track dependencies between model and view model and update view automatically. This article gives a very basic idea on observable. I recommend to download the source file and see for yourself how it actually works.
http://knockoutjs.com/
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
General News Suggestion Question Bug Answer Joke Rant Admin
4 messages have been posted for this article Visit http://www.codeproject.com/Articles/508820/BindingplusMetroplusUIplusTilespluswithplusKnockou to post and view comments on this article, or click here to get a print view with messages.