Contents
Create Sample Project
* From VS2013, create a new ASP.NET Web Application project named, e.g. ko1
* Select Empty template and add features:
– MVC
– Web API
* Also install packages:
– jQuery
– Bootstrap
– Knockout
* See this post for details on how setup a MVC5 and SPA sample project.
Toggle Elements
* Hide/Show elements
* Add/Remove elements
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <script src="~/Scripts/knockout-3.0.0.js"></script> <title>Test Observables</title> </head> <body> <div> <h1>Hello <span data-bind="text: computedFullName"></span>!</h1> <div data-bind="visible: showDescription"> <h2 data-bind="text: description"></h2> </div> <button type="button" data-bind="click: toggleDescription">Toggel Description</button></div> <!-- ko if: showDescription--> <h2 data-bind="text: description"></h2> <!-- /ko --> <script> function Person(firstName, lastName, description) { var self = this; self.firstName = firstName; self.lastName = lastName; self.description = description; self.computedCnt = 0; self.showDescription = ko.observable(false); self.computedFullName = ko.computed(function () { self.computedCnt++; return self.firstName + ' ' + self.lastName; }); self.toggleDescription = function () { self.showDescription(!self.showDescription()); }; }; var vm = new Person('John', 'Doe', 'Sample description.'); ko.applyBindings(vm); </script> </body> </html>
Bind Multiple View Models on a Single Page
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <script src="~/Scripts/knockout-3.0.0.js"></script> <title></title> </head> <body> <div id="greeting1"> <h1 data-bind="text: greetings()"></h1> </div> <div id="greeting2"> <h1 data-bind="text: greetings()"></h1> </div> <script> function Greeting(name) { var self = this; self.name = name; self.greetings = function(){ return 'Hello ' + self.name + '!'; }; }; var vm1 = new Greeting('John'); ko.applyBindings(vm1, document.getElementById('greeting1')); var vm2 = new Greeting('Jane'); ko.applyBindings(vm2, document.getElementById('greeting2')); </script> </body> </html>
Observable Examples
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <script src="~/Scripts/knockout-3.0.0.js"></script> <title>Test Observables</title> </head> <body> <div> <h1>Hello <span data-bind="text: computedFullName"></span>!</h1> <div data-bind="visible: showDescription"> <h2 data-bind="text: description"></h2> </div> <button type="button" data-bind="click: toggleDescription">Toggel Description</button></div> <!-- ko if: showDescription--> <h2 data-bind="text: description"></h2> <!-- /ko --> <script> function Person(firstName, lastName, description) { var self = this; self.firstName = firstName; self.lastName = lastName; self.description = description; self.computedCnt = 0; self.showDescription = ko.observable(false); self.computedFullName = ko.computed(function () { self.computedCnt++; return self.firstName + ' ' + self.lastName; }); self.toggleDescription = function () { self.showDescription(!self.showDescription()); }; }; var vm = new Person('John', 'Doe', 'Sample description.'); ko.applyBindings(vm); </script> </body> </html>
Template Binding Example
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <script src="~/Scripts/knockout-3.0.0.js"></script> <title></title> </head> <body> <table> <tbody data-bind="template: {name: 'greeting-template', foreach: greetings}"> </tbody> </table> <br /> <div data-bind="template: {name: 'greeting-template2', foreach: greetings}"> </div> <script type="text/html" id="greeting-template"> <tr> <td data-bind="text: greet"></td> <td data-bind="text: solute"></td> <td data-bind="text: $parent.name"></td> </tr> </script> <script type="text/html" id="greeting-template2"> <span data-bind="text: greet"></span> <span data-bind="text: solute"></span> <span data-bind="text: $parent.name"></span><br/> </script> <script> function Greetings(name) { var self = this; self.name = name; self.greetings = [ { greet: 'Hello', solute: 'Mrs.' }, { greet: 'Howdy', solute: 'Dr.' }, { greet: 'Hey', solute: 'Mr.' } ]; }; var vm = new Greetings('John'); ko.applyBindings(vm); </script> </body> </html>
Event Binding Example
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <script src="~/Scripts/knockout-3.0.0.js"></script> <title>Test Form1</title> </head> <body> <textarea data-bind="value: myText, event: { mouseover: clearText() }"></textarea> <br/> Character remaining: <span data-bind="text: charRemaining"></span> <br /> <span data-bind="text: msg"></span> <script> function MyText() { var self = this; self.myText = ko.observable('Enter text here'); self.maxCharAllowed = 25; self.msg = ko.observable(''); self.charRemaining = ko.computed(function () { return self.maxCharAllowed - self.myText().length; }); self.clearText = function () { self.myText(''); }; self.myText.subscribe(function () { self.msg('myText changed to: ' + self.myText()); }); }; var vm = new MyText(); ko.applyBindings(vm); </script> </body> </html>
Extending Observables
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <script src="~/Scripts/knockout-3.0.0.js"></script> <title>Extend Observable 1</title> </head> <body> <textarea data-bind="value: myText"></textarea><br/> Characters remaining: <span data-bind="text: charRemaining"></span> <script> ko.extenders.maxCharacters = function (target, max) { var result = ko.computed({ read: target, write: function (newValue) { alert(newValue); var current = target(); if (newValue.length <= max) { target(newValue); } else { target(current); target.notifySubscribers(current); }; } }).extend({ notify: 'always' }); return result; }; function ViewModel() { var self = this; self.maxCharacters = 10; self.myText = ko.observable('') .extend({ maxCharacters: self.maxCharacters }); self.charRemaining = ko.computed(function () { return self.maxCharacters - self.myText().length; }); }; var vm = new ViewModel(); ko.applyBindings(vm); </script> </body> </html>
Add Custom Functions to Observables
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <script src="~/Scripts/knockout-3.0.0.js"></script> <title>Add Custom Function to Observables</title> </head> <body> List of books: <ul> <!-- ko foreach: books --> <li> <input type="checkbox" data-bind="attr: { id: isbn }, checked: owned " /> <label data-bind="attr: { for: isbn }, text: title"></label> </li> <!-- /ko --> </ul> Books you own: <ul> <!-- ko foreach: booksOwned --> <li data-bind="text: title"></li> <!-- /ko --> </ul> <script> ko.observableArray.fn.booksOwned = function (property, value) { return ko.computed(function () { var allItems = this(); var machingItems = []; for (var i = 0; i < allItems.length; i++) { var current = allItems[i]; if (ko.unwrap(current[property]) === value) { machingItems.push(current); }; }; return machingItems; }, this); }; function ViewModel() { var self = this; self.books = ko.observableArray([ { title: 'Book1', isbn: '123451', owned: ko.observable(false) }, { title: 'Book2', isbn: '123452', owned: ko.observable(false) }, { title: 'Book3', isbn: '123453', owned: ko.observable(false) } ]); self.booksOwned = self.books.booksOwned('owned', true); }; var viewModel = new ViewModel(); ko.applyBindings(viewModel); </script> </body> </html>
Form Posting with AJAX
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Test Ajax Post 1</title> <script src="~/Scripts/jquery-1.10.2.js"></script> <script src="~/Scripts/knockout-3.0.0.js"></script> </head> <body> <form data-bind="submit: save2, with: person"> <input type="text" data-bind="value: firstName" placeholder="Enter first name" /> <br /> <input type="text" data-bind="value: lastName" placeholder="Enter last name" /> <br /> <input type="email" data-bind="value: email" placeholder="Enter email" /> <br /> <input type="submit" /> </form> <script> function ViewModel() { var self = this; self.person = { firstName : ko.observable(), lastName: ko.observable(), email: ko.observable() }; self.save = function (form) { $.ajax({ url: '/Home/AjaxPost1', data: ko.toJS(self.person), type: 'POST', contentType: 'application/x-www-form-urlencoded', error: function (xhr, status, error) { alert(xhr.responseText); }, success: function () { alert('Saved!'); } }); }; self.save2 = function (form) { $.ajax({ url: '/Home/AjaxPost1', data: ko.toJSON(self.person), type: 'POST', contentType: 'application/json', error: function (xhr, status, error) { alert(xhr.responseText); }, success: function () { alert('Saved by json!'); } }); }; }; var vm = new ViewModel(); ko.applyBindings(vm); </script> </body> </html>
Receiving Data with AJAX
* TagController:
public class TagController : ApiController { public IEnumerable<string> GetAllTags() { var tags = new List<string>(); tags.Add("Tag1"); tags.Add("Tag2"); tags.Add("Tag3"); return tags; } }
* Web page:
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <script src="~/Scripts/jquery-1.10.2.js"></script> <script src="~/Scripts/knockout-3.0.0.js"></script> <title>Test AJAX Receive One</title> </head> <body> <label for="tags">Filter a tag:</label> <input id="tags" data-bind="value: tag" /><br/> Tags matching: <ul> <!-- ko foreach: matchedTags --> <li data-bind="text: $data"></li> <!-- /ko --> </ul> <script> function ViewModel() { var self = this; self.availableTags = ko.observableArray([]); self.matchedTags = ko.observableArray([]); self.tag = ko.observable(); self.tag.subscribe(function (value) { self.matchedTags.removeAll(); if (value !== '') { $.ajax({ url: '/api/tag/', type: 'GET', contentType: 'application/json', dataType: 'json', success: function (data) { self.availableTags(data); for (var i = 0; i < self.availableTags().length; i++) { if (self.availableTags()[i].toLowerCase().indexOf(value) >= 0) { self.matchedTags.push(self.availableTags()[i]); }; }; }, error: function (xhr, status, error) { alert(xhr.responseText); } }); }; }); }; var vm = new ViewModel(); ko.applyBindings(vm); </script> </body> </html>