STRUCTURE
BEHAVIOR
PRESENTATION
The Eval JavaScript Empire
puts a heavy emphasis on
INTERFACE
LOGIC
PRESENTATION
The New Angular Republic
returns things to where they belong
in their natural forms
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(); }); });