The AngularJS Controller WeIGHT LOSS DIET

How Refactoring and Using UI-Router can Improve your Application

Who is this guy?

 

  • David Khourshid
  • Web developer @ Viewpost
  • Large-scale AngularJS App Development

Why Skinny Controllers?

  • "Fat models, skinny controllers"
  • Separation of concerns
  • Single Responsibility Principle
  • Simplicity and Reuse
  • Consolidated Unit Testing
  • Societal Perception of Beauty

"But It's SO Inconvenient"

  • Everything in one place
  • I don't mind copy-pasting
  • My view logic is complex
  • My deadline is tighter than my controller's jeans

WHAT MAKES CONTROLLERS FAT?

  • $scope-besity
  • in-$digest-ion
  • Statelessness
  • DOM Manipulation
  • Not using services
  • Too many dependencies
  • Following tutorials to the T
  • Shortcuts
  • Magic strings/numbers
$scope.newTodo = '';
$scope.editedTodo = null;

$scope.$watch('todos', function (newValue, oldValue) {
	$scope.remainingCount = $filter('filter')(todos, { completed: false }).length;
	$scope.completedCount = todos.length - $scope.remainingCount;
	$scope.allChecked = !$scope.remainingCount;
	if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
		todoStorage.put(todos);
	}
}, true);

// Monitor the current route for changes and adjust the filter accordingly.
$scope.$on('$routeChangeSuccess', function () {
	var status = $scope.status = $routeParams.status || '';

	$scope.statusFilter = (status === 'active') ?
		{ completed: false } : (status === 'completed') ?
		{ completed: true } : null;
});

Let's fix our obtuse Angular

Get rid of $scope. Trust me.

 

  • Use "Controller as" syntax
  • (Less) weight (on) $watchers
  • If you need it for something else, you can always inject it.

DO YOURSELF A SERVICE (OR THREE)

Defer logic to services

  • Separation of concerns!
  • Controllers should connect view-model and services
  • Business logic goes in services
  • State logic might go in controller
  • UI logic goes in directives

UI-ROUTER AND YOU (AND I)

STATE-ING THE OBVIOUS

  • Organize your app into states!
  • Give your controller a (new year's) resolution
  • Use services in resolves
  • Take advantage of params
<!-- Do this... -->
<a ui-sref="goat({name: goat.name})">...</a>

<!-- Instead of this... -->
<a ng-click="goats.editGoat(goat.name)">...</a>

let's see an example.