Web Unleashed 2013
Source of Truth for Application State
Describes the Relationship Between State and the DOM
function Controller($scope) { $scope.name = '{{name}}'; $scope.length = function() { return $scope.name.length; }; // this.length(); => {{ length() }} $scope.reset = function() { $scope.name = 'foo'; }; };
<input ng-model="name" value="{{name}}"/> <button ng-click="reset()">Reset</button> <div>Name: {{name}} Length: {{length()}} </div>
$scope.price = {{price}}; //... myModule.directive('numberInput', function () { return { template: '<input type="text"/>', restrict: 'E', require: 'ngModel', link: function($scope, element, attrs, modelCtrl) { element.on('blur', function() { $scope.$apply(function() { var num = parseInt(element.value.replace(/,/g, ''), 10); modelCtrl.$modelValue = num; }); }); modelCtrl.$render = function () { element.value = modelCtrl.$modelValue.toLocaleString(); }; // missing closing braces...
<label> Price: <number-input ng-model="price"></number-input></label>
var ViewModel = function() { this.name = ko.observable(''); this.length = ko.computed(function() { return this.name().length; }, this); // this.length(); => this.reset = function() { this.name('foo'); }; };
<input data-bind="value: name, valueUpdate: 'afterkeydown'" value=""/> <button data-bind="click: reset">Reset</button> <div>Name: <span data-bind="text: name"></span> Length: <span data-bind="text: length"></span></div>
<label>Order Date: {{purchaseOrder.createdAt | date:'MM/dd/yyyy'}}</label>
<label>Order Date: {{date purchaseOrder.createdAt 'MM/DD/YYYY'}}</label>
<label>Order Date: <span data-bind="text: fmt.date(purchaseOrder.createdAt, 'MM/DD/YYYY')"></span> </label>
Update the DOM to Reflect the Presentation Model
Translates DOM Events into Application Actions
viewModel.price = ko.observable(); ko.bindingHandlers.number = { init: function(element, valueAccessor) { var observable = valueAccessor(); element.addEventListener('blur', function() { var number = parseInt(element.value.replace(/,/g, ''), 10); observable(number); }); }, update: function(element, valueAccessor) { var number = ko.unwrap(valueAccessor()); element.value = number.toLocaleString(); }};
<label> Price: <input type="text" data-bind="number: price" /></label>
var VM = function() { this.name = ko.observable(''); this.inputHasFocus = ko.observable(); this.highlight = ko.computed(function () { return !(this.name() || this.inputHasFocus()); // }, this); }; ko.bindingHandlers['hasFocus'] = { init: function (element, valueAccessor) { var observable = valueAccessor(); $(element).on('focus', function () { observable(true); }); $(element).on('blur', function () { observable(false); }); // ...
<label data-bind="css: {'hot-pink': highlight}">Favorite Fruit:</label> <input id="fruit" data-bind="value: name, hasFocus: inputHasFocus"/>