Skip to content

Instantly share code, notes, and snippets.

@greyaperez
Last active May 2, 2018 14:31
Show Gist options
  • Save greyaperez/9fa575682749781fc0b0 to your computer and use it in GitHub Desktop.
Save greyaperez/9fa575682749781fc0b0 to your computer and use it in GitHub Desktop.
Angular Best Practices

Angular Best Practices

by Tim A. Perez


Important Common Pitfalls to Avoid:

  • $watch, $watchCollection, etc – Avoid using any kind of watches in General. These can quickly and exponentially increase digest cycles and can be completely avoided with good usage of inheritance.
  • Event Driven Logic – this makes code extremely difficult to maintain/debug as it grows. This includes $broadcast, $emit, $on, etc…
  • Avoid over-utilization of the $scope
  • Everything should be private unless it’s being used directly by an element on the DOM.
  • Group scope properties as sub-properties of umbrella properties (examples further down)

Good Practices:

  • Keep Controllers Light – logic should be abstracted and delegated to factories or services when dealing with actual $http requests.

  • ALWAYS DECLARE vars at the top of it’s relevant scope. This will help avoid undefined errors and improve clarity.

  • Use Expressions Over Method Calls in the DOM to avoid additional digest cycles:

    Example: BAD

    <div ng-if=“isTacoYummy()”>
    

    Example: GOOD

    <div ng-if=“taco.cheese.count > 1 && taco.meat !== ‘ground rat'">
    
  • Avoid Direct Reference to Scope Props – Anytime you use a property in the DOM, you should be referencing a sub-property (dot notation). Example: BAD

    {{name}}
    

    Example: GOOD

    {{user.name}}
    

    This helps to avoid awkward conflicts with prototypical inheritance and provides a clearer distinction of the parent context. A good way to do this is by utilizing the 'controller as' syntax (see further below).


One of the most common pitfalls I tend to see is bloated controllers. As mentioned, controllers should delegate the majority of the logic to appropriately grouped factories/services and instead should mainly focus on two aspects.

  1. Core Verb Methods (think façade pattern)
  2. Storing State

About 99% of any other view-model/user triggered method calls should be from the appropriate usage of directives, which should have their own set of controllers/services/etc.


How do you know you need a factory… what goes in it?

The purpose of a factory is to contain a tightly group of related logic together (single purpose). Think, class abstraction in conventional OOP.


Use "Controller As" Syntax

The benefits are substantial when considering to utilize the "controller as" syntax that was introduced in Angular 1.2. It helps to make code easier to read and implicitly enforces the use of dot notation when utilizing scope properties. It also allows for easier access to props and methods from within the controller. Implementing and using it is a cinch.

DOM: ng-controller="HomeController as Home" Directive Config: { restrict: 'EA', templateUrl: 'app/components/widget.directive.html' controller: WidgetController, controllerAs: 'Widget', bindToController: true ... }

Then within your controller you would reference your scope with the "this" keyword. It would probably be idea to add a reference to the "this" var to avoid the need to use .bind() on functions.

// Inside the Controller
var home = this;

// Now 'home' is like using $scope

Finally, to reference the controller's scope properties...

<p>{{home.someProp}}</p>

<input ng-model="widget.firstName">
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment