What jQuery is and how we use it
What AngularJS is and how we use it
When to use what and what the difference is
How AngularJS expects you to think to use correctly
jQuery in AngularJS
Where to go from here
Might seem small, look at code in many slidesAnyone know what jQuery is?
JavaScript library released in 2006, created for DOM manipulation by John Resig
50% of the websites, wordpress, joomla
Bundle of functions / methods
Specific, well-defined operations
Tool for a specific need
Underscore, backbone, mootools, handlebars, zepto
<div> <input type="text" id="todoName" placeholder="Name of todo"> <button id="addTodo" type="submit">Add</button> <ul id="todoList"> <li> <span class="text">Item 1</span> <a href="#" class="todoRemove">Remove</a> </li> </ul> </div> <div id="todoEdit" style="display: none;"> <input type="text" id="todoEditField"> <button type="submit">Save</button> </div>
No clear connection between button and text field
No clear connection between list and actual items
We don't know what's going on. We can always guess but guessing is dangerous.
We want to be able to read code as smoothly as possible, spend more time reading code than writing code
$(document).ready(function () { var addItem = function (value) { $('#todoList').append('<li><span class="text">' + value + '</span> <a href="#" class="todoRemove">Remove</a></li>') } $(document).on('click', '#addTodo', function () { addItem($('#todoName').val()); }); $(document).on('click', '.todoRemove', function (ev) { ev.preventDefault(); $(this).parent().remove(); }); $(document).on('click', '#todoList span', function () { var itemText = $(this).text(); $(this).parent().remove(); $('#todoEdit input').val(itemText); $('#todoEdit').show(); }); $(document).on('click', '#todoEdit button', function () { var itemText = $('#todoEdit input').val(); addItem(itemText); $('#todoEdit').hide(); }) })
References that will break once moved.
Does stuff it shouldn't care about
In the wrong context, does the wrong thing
Anyone know what AngularJS is?
Open source framework for developing webapplications
Created by Misko Hevery and Adam Abrons 2009
Started out to help webdesigners who isn't developer to spray on some extra HTML and magic with data storage
Misko redesigning Google Feedback admin panel
6 months, issues with productivity
Misko said "with this project I'm working on the side, I could have done this in two weeks!"
Google accepted the challenge "Prove us wrong"
Took him three weeks, not two
From 17'000 LOC, down to 1'500 LOC, same application
Abstract design
Way of life
User code is in framework, not user code calling framework
"Don't call us, we call you" Hollywood principle, Inversion of control
"You call library code, framework calls your code"
Quick about MVC
DOM is for showing stuff and interactions
All the rest is elsewhere
<div ng-app="plnkr"> <div ng-controller="IndexCtrl"> <input type="text" ng-model="newTodo.name"> <button type="submit" ng-click="addTodo(newTodo)">Add</button> <ul> <li ng-repeat="item in items"> <span ng-click="editTodo(item)">{{ item.name }}</span> <a href="#" ng-click="removeTodo(item)">Remove</a> </li> </ul> <div ng-show="editingTodo"> <input type="text" ng-model="editingTodo.name"> <button ng-click="editingTodo = null">Done</button> </div> </div> </div>
You can see clear connections
Stuff can be moved and still working
No classes/ids because that's about styling, other concern!
var app = angular.module('plnkr', []); app.controller('IndexCtrl', function($scope) { $scope.items = [ { name: 'Item 1' }, { name: 'Item 2' } ]; $scope.newTodo = { name: "New todo item" }; $scope.addTodo = function(newTodo) { $scope.items.push(angular.copy(newTodo)); } $scope.removeTodo = function(item) { var index = $scope.items.indexOf(item); $scope.items.splice(index, 1); } $scope.editTodo = function(item) { $scope.editingTodo = item; } })Does only what it needs to do. No view stuff here!
Which is the best one?
None because the question is bad, different use cases
<li> <span class="text">Item 1</span> <a href="#" class="todoRemove">Remove</a> </li>
$(document).on('click', '.todoRemove', function(ev) { ev.preventDefault(); $(this).parent().remove(); });Stuck to the place where it's created Does stuff that could change in the future
<a href="#" class="somethingElse"></a>
<li ng-repeat="item in items"> <span ng-click="selectTodo(item)">{{ item.name }}</span> <a href="#" ng-click="removeTodo(item, $event)">Remove</a> </li>
$scope.removeTodo = function (item, $event) { $event.preventDefault(); var index = $scope.items.indexOf(item); $scope.items.splice(index, 1); }
Just a method, could be called from anywhere, don't care about outside
Remove selectedWrite code in two ways
AngularJS extends HTML, embraces HTML, what happened in the demo
Imperative - How to do something, end up with what we wanted to do
Declarative - What we want to do, how it does it is not a concern of ours
Don't decide the flow of the control
Abstract away logic, seperation of concerns
$('#addTodo').on('click', function(ev) { ev.preventDefault(); addItem($('#todoName').val()); });How we want to add the item
<button type="submit" ng-click="addTodo(newTodo)">Add</button>Just add the goddamn todo
jQuery - Start with website, extend with functionality
AngularJS - Start with thinking, doing foundation, add functionality, end up with website
jQuery - Websites, no data, minimal interactions
AngularJS - Application, a lot of interactions, contains data, communicates with something (db / backend)
Thinking and reflection moment
jQuery, library for the dom, tell it what do, looking on html isn't enough
AngularJS, framework to build applications, we extend it after it's law and principles
You know library, now it's time for framework
First steps first
"Don't even use jQuery. Don't even include it. It will hold you back"
When I started out, I would often reach for the jQuery solution, easy and fast. Not including jQuery anymore brought me to seek native angularjs solution which I'm now benifitting from.angular.module('friendList', []) .directive('list', function () { return { restrict: 'E', scope: { 'ngModel': '=' }, template: '<pre><code>{{ ngModel }}</code></pre>' } })
<div> Your friendlist! <list ng-model="user.friends"></list> </div>
<div> Mauros friendlist! <list ng-model="User('userId').friends"></list> </div>
angular.module('ui.mask', []) .directive('uiMask', ['uiMaskConfig', function (maskConfig) { return { priority: 100, require: 'ngModel', restrict: 'A', compile: function uiMaskCompilingFunction(){ var options = maskConfig; [...]
angular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition']) .directive('progress', function() { return { restrict: 'EA', replace: true, controller: 'ProgressBarController', scope: { value: '=percent', onFull: '&', onEmpty: '&' [...]
angular.module('restangular', []) .provider('Restangular', function() { // Configuration var Configurer = {}; Configurer.init = function(object, config) { /**
it("should display the welcome text properly", function() { var element = $compile('<div welcome="user"></div>')($rootScope); expect(element.text()).to.match(/Welcome/i); })
angular.module('User', []) .provider('User', function () { [...] }); angular.module('FriendList', []) .directive('list', function () { return { [...] } }) angular.module('mainApp', ['User', 'FriendList']) .controller('IndexCtrl', function($scope, User) { $scope.user = User.current(); })
<div ng-controller="IndexCtrl"> Your friends! <list ng-model="user.friends"></list> </div>
Model and Controller above
View below
Subset of jQuery for DOM manipulation
Reusable components
Creating new HTML elements, available for reuse everywhere!
<div> <pre>{{ users | json }}</pre> </div>
<div style="float: right;"> <user-image user="current_user"></user-image> </div>
<user-list users="users"></user-list>
<div style="float: left;"> <user-card user="current_user"></user-card> </div>
user-image for showing image
user-card for showing image and related information
user-list for list of user-cards
<div> <user-image user="current_user"></user-image> </div> <div> <user-card user="current_user"></user-card> </div> <div> <user-list users="users"></user-list> </div>
app.directive('userImage', function () { return { restrict: 'E', scope: { 'user': '=' }, template: '<img height="50" ng-src="{{user.image}}">' } }) app.directive('userCard', function() { return { restrict: 'E', scope: { 'user': '=' }, template: '<div><h3>{{ user.name }}</h3>' + '<h5>@{{ user.twitter }}</h5>' + '<user-image user="user"></user-image></div>' } }) app.directive('userList', function() { return { restrict: 'E', scope: { 'users': '=' }, template: '<div><user-card ng-repeat="user in users" user="user"></user-card></div>' } })
<change-color color="purple"></change-color> <div ng-repeat="color in colors"> <change-color color="{{color}}"></change-color> </div>
app.controller('IndexCtrl', function($scope) { $scope.colors = ['red', 'blue', 'green', 'yellow']; }) app.directive('changeColor', function() { return { restrict: 'E', scope: { 'color': '@' }, template: '<h3>Change my color to {{ color }} by clicking on me!!!</h3>', link: function (scope, element) { element.bind('click', function () { element.css('color', scope.color); }); } } })
Take time to think before coding
victor@vreasy.com @victorbjelkholm github.com/victorbjelkholm