On Github mb-dev / angular-js-presentation
by Moshe Bergman
(Except for large amount of bindings)
(Both in terms of code structure and robustness)
puts a heavy emphasis on
STRUCTURE
BEHAVIOR
PRESENTATION
The Eval JavaScript Empire
INTERFACE
LOGIC
PRESENTATION
The New Angular Republic
returns things to where they belong
in their natural forms
Intriguingly,
the uprising of AngularJS in 2013
is coincident with...
To get started:
<div ng-app="app"> <div ng-view=""></div> </div>
angular.module('app', ['app.services', 'app.directives', 'app.controllers', 'ngRoute']).config(function($routeProvider, $locationProvider) { $routeProvider.when("/accounts/?:userIdOrScreenName?", { templateUrl: "/accounts/partials/main_page", controller: 'UserDetailsIndexCtrl' }); $routeProvider.otherwise({ redirectTo: "/accounts/" }); $('.navbar').removeClass('navbar-inverse'); return $locationProvider.html5Mode(true); });
angular.module('app.controllers', ['app.services']).controller('UserDetailsIndexCtrl', function($scope, userQuery, $location, $routeParams) { var onUserDataArrived = function(result) { $scope.user = {id: result.data.id, name: result.data.profile.name, screen_name: result.data.profile.screen_name, image: result.data.profile.profile_image_urls.normal.http_url}; } if ($routeParams.userIdOrScreenName) { $scope.userIdOrAccount = $routeParams.userIdOrScreenName; userQuery.queryUser($routeParams.userIdOrScreenName).then(onUserDataArrived); } $scope.onSelectUser = function(e) { $location.path('/accounts/' + $scope.userIdOrAccount); }; }
<form ng-submit="onSelectUser()"> <input type="text" ng-model="userIdOrAccount" placeholder="User ID or @SN"> </form> <span class="name">{{user.name}}</span>
angular.module('app.services', []).factory('userQuery', function($http, $q) { return { queryUser: function(userIdOrScreenName) { return $http.get('/accounts/user_stats/' + userIdOrScreenName.toString()); } }; });
Directives can be confusing at first. Many ways to construct them.
directive('ngConfirmClick', function() { return { link: function (scope, element, attr) { var msg = attr.ngConfirmClick || "Are you sure?"; var clickAction = attr.confirmedClick; element.bind('click',function (event) { if ( window.confirm(msg) ) { scope.$eval(clickAction) } }); } }; })
Used for transforming data (pipe).
.filter('multiple', function () { return function (input) { return '' + input + 'X'; }; })
<tr ng-repeat="friend in friends | filter:searchText"> </tr> <span>{{amount | currency}}</span>
describe('app.controllers::UserDetailsIndexCtrl', function() { var $controller, $location, $scope, userQuery, $q, deferred; beforeEach(module('app.controllers')); beforeEach(inject(function($rootScope, _$location_, _$controller_, _$q_) { $scope = $rootScope.$new(); $location = _$location_; return userQuery = { queryUser: function() { deferred = $q.defer(); return deferred.promise; } }; }));
it('should query user information when submitted with /userid=1', function() { spyOn(userQuery, 'queryUser').andCallThrough(); $controller('UserDetailsIndexCtrl', { $scope: $scope, $location: $location, $routeParams: { userIdOrScreenName: 3 }, userQuery: userQuery }); expect(userQuery.queryUser).toHaveBeenCalled(); }); });