On Github ericop / js-mvc-presentation
A practical look JS MV* Frameworks: Angular 1.5, Ember, VueJS vs. Knockout (with or without components)
Created by EricOP
Press ESC to see the overall roadmap Press SPACE to progress through each slide
Knockout
Now to Compare to:
ember
Angular
VueJS
With Components
(more on components later)
Nothing Fancy: a form calls an API, a checkbox with a conditional if, and a forEach loop on the results
Hold down Alt and click to zoom in and out on the slide
Hide Events with Meals
// JS Controller, Component, or ViewModel Bits var myModel = new function () { var self = this; self.hideEventsWithMeals = ko.observable(false); self.firstName = ko.observable("Eric"); self.lastName = ko.observable("Johnson"); self.myEvents = ko.observableArray([]); self.addEvent = function (event) { self.myEvents.push( { id: event.Id, urlId: '/Admin/Details/' + event.Id, name: event.Name, description: event.Description, location: event.Location, date: event.Date, startTime: event.StartTime, endTime: event.EndTime, hasMeal: event.HasMeal, mealDescription: event.MealDescription, pastDate: new Date(event.Date) < new Date() }) console.log('event=', event); } self.alert = function () { alert("Hello, I'm " + self.firstName() + " " + self.lastName() + ", the stuff!"); }; self.findMyEvents = function () { var that = self; //clear old events that.myEvents([]); $.ajax({ url: '@Url.Action("MyEventsAPI", "Home")', dataType: 'json', method: 'GET', async: false, data: { firstName: self.firstName(), lastName: self.lastName() }, success: function (data) { var responseData = jQuery.parseJSON(data); for (i = 0; i < responseData.length; i++) { //console.log('for loop', i, responseData[i]); that.addEvent(responseData[i]); } } }); } }; // Knockout bind needed at end ko.applyBindings(myModel);
Hold down Alt and click to zoom in and out on the slide
{{input type="checkbox" name="hideEventsWithMeals" checked=hideEventsWithMeals}} Hide Events with Meals {{event.name}} {{event.description}} {{event.location}} {{event.hasMeal}} {{event.mealDescription}} {{event.startTime}} {{event.endTime}} {{event.name}} {{event.description}} {{event.location}} {{event.hasMeal}} {{event.mealDescription}} {{event.startTime}} {{event.endTime}}
var myEventsApp = Ember.Application.create({ rootElement: '#myEvents', }); myEventsApp.ApplicationController = Ember.Controller.extend({ firstName: "Eric", lastName: "Johnson", myEvents: [], hideEventsWithMeals: false, myEventsWithoutMeals: Ember.computed.filterBy('myEvents', 'hasMeal', false), actions: { alert: function () { alert("Hello, I'm " + this.get('firstName') + " " + this.get('lastName') + ", the stuff!"); }, addEvent: function (event) { this.myEvents.push( { id: event.Id, //urlId: '/Admin/Details/' + event.Id, not needed name: event.Name, description: event.Description, location: event.Location, date: event.Date, startTime: event.StartTime, endTime: event.EndTime, hasMeal: event.HasMeal, mealDescription: event.MealDescription, pastDate: new Date(event.Date) < new Date(), hideThisMealEvent: event.hasMeal && this.get('hideEventsWithMeals') }) console.log('event=', event); }, findMyEvents: function () { var that = this; //clear old events that.set('myEvents', []); $.ajax({ url: '@Url.Action("MyEventsAPI", "Home")', dataType: 'json', method: 'GET', async: false, data: { firstName: that.get('firstName'), lastName: that.get('lastName') }, success: function (data) { var responseData = jQuery.parseJSON(data); for (i = 0; i < responseData.length; i++) { //console.log('for loop', i, responseData[i]); that.send('addEvent', responseData[i]); } } }); } } })
Hold down Alt and click to zoom in and out on the slide
Hide Events with Meals {{event.name}} {{event.description}} {{event.date}} {{event.location}} {{event.hasMeal}} {{event.mealDescription}} {{event.startTime}} {{event.endTime}}
// JS Controller, Component, or ViewModel Bits var myEventsApp = angular.module('myEvents', []); myEventsApp.controller('MyEventsController', function ($scope, $http) { var self = this; $scope.firstName = "Eric"; $scope.lastName = "Johnson"; $scope.myEvents = []; self.alert = function () { alert("Hello, I'm " + $scope.firstName + " " + $scope.lastName + ", the stuff!"); }; self.addEvent = function (event) { $scope.myEvents.push( { id: event.Id, //urlId: '/Admin/Details/' + event.Id, not needed name: event.Name, description: event.Description, location: event.Location, date: event.Date, startTime: event.StartTime, endTime: event.EndTime, hasMeal: event.HasMeal, mealDescription: event.MealDescription, pastDate: new Date(event.Date) < new Date() }) console.log('event=', event); } self.findMyEvents = function () { var that = self; //clear old events $scope.myEvents = []; $http({ url: '@Url.Action("MyEventsAPI", "Home")', responseType: 'json', method: 'GET', async: false, params: { firstName: $scope.firstName, lastName: $scope.lastName } }).then(function (response) { var responseData = angular.fromJson(response.data); for (var i = 0; i < responseData.length; i++) { //console.log('for loop', i, responseData[i]); that.addEvent(responseData[i]); } }); } });
Hold down Alt and click to zoom in and out on the slide
Hide Events with Meals {{event.name}} {{event.description}} {{event.date}} {{event.location}} {{event.hasMeal}} {{event.mealDescription}} {{event.startTime}} {{event.endTime}}
// JS Controller, Component, or ViewModel Bits new Vue({ el: '#myEvents', data: { hideEventsWithMeals: false, firstName: "Eric", lastName: "Johnson", myEvents: [] }, methods: { alert: function () { alert("Hello, I'm " + this.firstName + " " + this.lastName + ", the stuff!"); }, addEvent: function (event) { this.myEvents.push( { id: event.Id, //urlId: '/Admin/Details/' + event.Id, not needed name: event.Name, description: event.Description, location: event.Location, date: event.Date, startTime: event.StartTime, endTime: event.EndTime, hasMeal: event.HasMeal, mealDescription: event.MealDescription, pastDate: new Date(event.Date) < new Date() }) console.log('event=', event); }, findMyEvents: function () { var that = this; //clear old events that.myEvents = []; $.ajax({ url: '@Url.Action("MyEventsAPI", "Home")', dataType: 'json', method: 'GET', async: false, data: { firstName: this.firstName, lastName: this.lastName }, success: function (data) { var responseData = jQuery.parseJSON(data); for (i = 0; i < responseData.length; i++) { //console.log('for loop', i, responseData[i]); that.addEvent(responseData[i]); } } }); } } });
Hold down Alt and click to zoom in and out on the slide
// JS Controller, Component, or ViewModel Bits var myModel = new function () { var self = this; self.firstName = ko.observable("Eric"); self.lastName = ko.observable("Johnson"); self.myEvents = ko.observableArray([]); self.addEvent = function (event) { self.myEvents.push( { id: event.Id, urlId: '/Admin/Details/' + event.Id, name: event.Name, description: event.Description, location: event.Location, date: event.Date, startTime: event.StartTime, endTime: event.EndTime, hasMeal: event.HasMeal, mealDescription: event.MealDescription }) console.log('event=', event); } self.alert = function () { alert("Hello, I'm " + self.firstName() + " " + self.lastName() + ", the stuff!"); }; self.findMyEvents = function () { var that = self; //clear old events that.myEvents([]); $.ajax({ url: '@Url.Action("MyEventsAPI", "Home")', dataType: 'json', method: 'GET', async: false, data: { firstName: self.firstName(), lastName: self.lastName() }, success: function (data) { var responseData = jQuery.parseJSON(data); for (i = 0; i < responseData.length; i++) { //console.log('for loop', i, responseData[i]); that.addEvent(responseData[i]); } } }); } }; var resultsModel = function (params) { var self = this; self.hideEventsWithMeals = ko.observable(false); self.results = params.results; // The current item will be passed as the first parameter, so we know which event.id we have self.viewDetails = function (event) { window.location.replace("/Admin/Details/" + event.id); } } ko.components.register('results-table', { template: { element: 'results-table-template' }, viewModel: resultsModel }); var overallViewModel = { myModel: myModel, resultsModel: new resultsModel(myModel.myEvents) }; ko.applyBindings(overallViewModel);
Hold down Alt and click to zoom in and out on the slide
{{input type="checkbox" name="hideEventsWithMeals" checked=hideEventsWithMeals}} Hide Events with Meals {{event.name}} {{event.description}} {{event.location}} {{event.hasMeal}} {{event.mealDescription}} {{event.startTime}} {{event.endTime}} {{event.name}} {{event.description}} {{event.location}} {{event.hasMeal}} {{event.mealDescription}} {{event.startTime}} {{event.endTime}}
var myEventsApp = Ember.Application.create({ rootElement: '#myEvents', }); myEventsApp.MyEventsComponent = Ember.Component.extend({ firstName: "Eric", lastName: "Johnson", myEvents: [], actions: { alert: function () { alert("Hello, I'm " + this.get('firstName') + " " + this.get('lastName') + ", the stuff!"); }, addEvent: function (event) { this.myEvents.push( { id: event.Id, //urlId: '/Admin/Details/' + event.Id, not needed name: event.Name, description: event.Description, location: event.Location, date: event.Date, startTime: event.StartTime, endTime: event.EndTime, hasMeal: event.HasMeal, mealDescription: event.MealDescription, pastDate: new Date(event.Date) < new Date() }) console.log('event=', event); }, findMyEvents: function () { var that = this; //clear old events that.set('myEvents', []); $.ajax({ url: '@Url.Action("MyEventsAPI", "Home")', dataType: 'json', method: 'GET', async: false, data: { firstName: that.get('firstName'), lastName: that.get('lastName') }, success: function (data) { var responseData = jQuery.parseJSON(data); for (i = 0; i < responseData.length; i++) { //console.log('for loop', i, responseData[i]); that.send('addEvent', responseData[i]); } } }); } } }); myEventsApp.ResultsTableComponent = Ember.Component.extend({ ResultsTableComponent: [], hideEventsWithMeals: false, myEventsWithoutMeals: Ember.computed.filterBy('results', 'hasMeal', false), actions: { viewDetails: function (eventId) { window.location.replace("/Admin/Details/" + eventId); } } });
*Press B or . on your keyboard to go black screen for a mic-drop. *