- Details
- Written by: Stanko Milosev
- Category: Knockout
- Hits: 1864
/*global google, ko*/ /*jshint esversion: 6 */ /* jshint -W031 */ (function (ns){ "use strict"; var mapOptions, mapCanvas, map, gpsViewModel; mapOptions = { zoom: 6, center: { lat: -34.397, lng: 150.644}, mapTypeId: google.maps.MapTypeId.ROADMAP }; mapCanvas = document.getElementById('map-canvas'); if (!map) { map = new google.maps.Map(mapCanvas, mapOptions); gpsViewModel = new ns.GpsViewModel(); ko.applyBindings(gpsViewModel); google.maps.event.addListener(map, 'click', function (evemt) { new google.maps.Circle({ strokeColor: "#FF0000", strokeOpacity: 0.8, strokeWeight: 2, fillColor: "#FF0000", fillOpacity: 0.35, map, center: { lat: gpsViewModel.lat(), lng: gpsViewModel.lng()}, radius: Math.sqrt(603502) * 100 }); }); google.maps.event.addListener(map, 'mousemove', function (event) { gpsViewModel.lat(event.latLng.lat()); gpsViewModel.lng(event.latLng.lng()); }); } }(window.milosev));gps.js:
/*global window, ko*/ (function (ns) { "use strict"; var self; ns.GpsViewModel = function () { self = this; self.lat = ko.observable(); self.lng = ko.observable(); return { lat: self.lat, lng: self.lng }; }; }(window.milosev));Notice line:
radius: Math.sqrt(603502) * 100
That was just copy / paste, otherwise radius is in meters Source download from here. Live example:
Langitude:
Longitude:
- Details
- Written by: Stanko Milosev
- Category: Knockout
- Hits: 1954
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="js/index.js"></script> <script type="text/javascript" src="js/lib/knockout-3.5.1.js"></script> <script type="text/javascript" src="js/lib/jquery-3.4.1.min.js"></script> </head> <body onload="DoApply()"> Cities: <span data-bind="template: {name: 'cities-template', foreach: cities}"></span> <script type="text/html" id="cities-template" > <br/> <input data-bind="id: id, name: name" type="checkbox"> <label data-bind="for: name, text: name"></label> </script> </body> </html>JS:
function MyViewModel() { var self = this; self.cities = ko.observableArray([]); $.getJSON("cities.json", function(data) { data.forEach(function (item, index) { self.cities.push({name: item.Name, id:item.ID}); }); }) } function DoApply() { ko.applyBindings(new MyViewModel()); }Where cities.json looks like:
[ { "ID": 0, "Name": "Bonn" }, { "ID": 0, "Name": "Petrovaradin" }, { "ID": 0, "Name": "Novi Sad" }, { "ID": 0, "Name": "Balingen" } ]Live example see here. --- Edit: observableArray must be global, something like ns.cities = ko.observableArray([]);, and pushed should be observable:
/*global window, ko*/ (function (ns) { "use strict"; ns.CitiesViewModel = function () { var self = this, getCities = new GetCities(), city = ko.observable(); ns.cities = ko.observableArray(); function GetCities() { $.getJSON("api/cities", function (data) { data.forEach(function (item, index) { city({ name: item.Name, id: item.ID }); ns.cities.push(city()); }); }); } return { myCities: getCities } } }(window.milosev));--- Or even better and make it part of CitiesViewModel:
/*global window, ko, $*/ (function (ns) { "use strict"; ns.CitiesViewModel = function () { var self = this, getCities = new GetCities(), city = ko.observable(); function GetCities() { self.cities = ko.observableArray(); $.getJSON("api/cities", function (data) { data.forEach(function (item, index) { city({ name: item.Name, id: item.ID }); self.cities.push(city()); }); }); return self.cities; } return { cities: getCities }; }; }(window.milosev));
- Details
- Written by: Stanko Milosev
- Category: Knockout
- Hits: 3704
Example which I am using when I want to see which model I am sending to knockout.
HTML:
<body> <div data-bind="text: function() {debugger; return myText}()"></div> </body>
JS:
/*global ko*/ (function () { "use strict"; function MyModel() { var self = this; self.myText = ko.observable("Test"); } MyModel = new MyModel(); ko.applyBindings(MyModel); }());
Notice in HTML line:
<div data-bind="text: function() {debugger; return myText}()"></div>
In that line you can see debugger, and also return, which will force function to return value. Now you can debug knockout.
- Details
- Written by: Stanko Milosev
- Category: Knockout
- Hits: 3907
In custom bindings you can pass whole object, parse it and later use it, also you can pass a function (like observable for example).
HTML
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script type="text/javascript" src="/knockout-3.3.0.js"></script> <script type="text/javascript" src="/index.ko.extension.js" defer></script> <script type="text/javascript" src="/index.js" defer></script> </head> <body> <div data-bind="myBind: {propertyOne: testOne, propertyTwo: testTwo}"></div> </body> </html>
Here notice part:
<div data-bind="myBind: {propertyOne: testOne, propertyTwo: testTwo}"></div>
Now index.js:
/*global window, ko*/ function MyLog(msg) { function doTheLog(msg) { console.log(msg); } return { doTheLog: doTheLog } }; window.doSomething = new MyLog(); window.testOne = "test one"; window.testTwo = "test two"; ko.applyBindings();
Here notice that I have created global variables testOne and testTwo, I need them for binding.
index.ko.extension.js:
/*global ko, console*/ /*jslint unparam: true*/ ko.bindingHandlers.myBind = { init: function (element, valueAccessor) { "use strict"; var myObjExample = ko.unwrap(valueAccessor()); doSomething.doTheLog(myObjExample.propertyOne); doSomething.doTheLog(myObjExample.propertyTwo); } }; /*jslint unparam: false*/
Here notice:
var myObjExample = ko.unwrap(valueAccessor());
With that I am actually parsing my object.
Unit test looks like this:
/*global describe, it, expect, beforeEach, ko, window, document, $*/ describe("my bind", function () { "use strict"; var sut; beforeEach(function () { //'<div data-bind="myBind: {propertyOne: testOne, propertyTwo: testTwo}"></div>' var myDiv = document.createElement('div'); myDiv.setAttribute("data-bind", "myBind: {propertyOne: testOne, propertyTwo: testTwo}"); document.body.appendChild(myDiv); window.testOne = "test one"; window.testTwo = "test two"; window.doSomething = jasmine.createSpyObj('MyLog', ['doTheLog']); ko.applyBindings(); }); it("gets object from value acessor", function () { expect(window.doSomething.doTheLog).toHaveBeenCalled(); }); });
Example download from here.
---
Actually, better unit test looks like:
/*global describe, it, expect, beforeEach, ko, window, document*/ describe("my bind", function () { "use strict"; var sut, testOne, testTwo; beforeEach(function () { var myDiv = document.createElement('div'); testOne = jasmine.createSpy("testOne"); testTwo = jasmine.createSpy("testTwo"); myDiv.setAttribute("data-bind", "myBind: {testOne: testOne, testTwo: testTwo}"); document.body.appendChild(myDiv); window.doSomething = jasmine.createSpyObj('MyLog', ['doTheLog']); ko.applyBindings({testOne: testOne, testTwo: testTwo}); }); it("gets object from value acessor", function () { expect(window.doSomething.doTheLog).toHaveBeenCalled(); }); });
Notice first my binding:
myDiv.setAttribute("data-bind", "myBind: {testOne: testOne, testTwo: testTwo}");
Then the apply bindings:
ko.applyBindings({testOne: testOne, testTwo: testTwo});
Version with this test download from here.