Resolves with ngRoute

Objectives

  • Describe the function of a resolve
     

  • Use a resolve to inject data into a controller

What is a Resolve

Default State transition in ngRoute

State Changes due to user action

Controller for that state is instantiated

What is a Resolve

Default State transition in ngRoute

State Changes

Controller starts


$stateProvider
  .state('todos', {
    url: '/',
    controller: "TodosController",
    templateUrl: "templates/index.html"
});
app.controller("TodosController", 
function($scope, TodoService){
  TodoService.getTodos()
  .then(function(todos){
    $scope.todos = todos.data;
  }).catch(function(err){
    $scope.errors = err;
  });
});

What is a Resolve

Default State transition in ngRoute

State Changes

Controller starts


$stateProvider
  .state('todos', {
    url: '/',
    controller: "TodosController",
    templateUrl: "templates/index.html"
});
app.controller("TodosController", 
function($scope, TodoService){
  TodoService.getTodos()
  .then(function(todos){
    $scope.todos = todos.data;
  }).catch(function(err){
    $scope.errors = err;
  });
});

Data Fetched and returned

What is a Resolve

Default State transition in ngRoute

State Changes

Controller starts

Data Fetched and returned

The problem is that if this is slow, our user will see flickering as the two way data-bindings update.

Especially if there are multiple requests.

What is a Resolve

State transition with Resolve

State Changes

Resolves are evaluated

Controller starts

Data Fetched and returned

What is a Resolve

State transition with Resolve

State Changes

Resolves are evaluated

Controller starts

$stateProvider
  .state('todos', {
    url: '/',
    controller: "TodosController",
    templateUrl: "templates/index.html",
    resolve: {
      TodoData: function(TodoService) {
        return TodoService.getTodos();
      }
    }        
});
app.controller("TodosController", 
function($scope, TodoData){
  $scope.todos = TodoData;
});

What is a Resolve

State transition with Resolve

State Changes

Resolves are evaluated

Controller starts

Now when our controller tries to instantiate we already have all the data

Using a Resolve

Step 1, give your route a 'resolve'

$stateProvider
  .state('todos', {
    url: '/',
    controller: "TodosController",
    templateUrl: "templates/index.html",
    resolve: {
      // What goes here?
    }        
});
app.controller("TodosController", 
function($scope){

});

Notice the property 'resolve'.

This must always be an object.

Using a Resolve

Step 2, give the resolve properties

$stateProvider
  .state('todos', {
    url: '/',
    controller: "TodosController",
    templateUrl: "templates/index.html",
    resolve: {
      TodoData: // What goes here?
    }        
});
app.controller("TodosController", 
function($scope, TodoData){
  $scope.todos = TodoData;
});

Notice that the property key is also the value we can inject into our controller

Using a Resolve

Step 3, define the property

$stateProvider
  .state('todos', {
    url: '/',
    controller: "TodosController",
    templateUrl: "templates/index.html",
    resolve: {
      TodoData: function(TodoService) {
        return TodoService.getTodos();
      }
    }        
});
app.controller("TodosController", 
function($scope, TodoData){
  $scope.todos = TodoData;
});

Resolves must be either a function or a string.  Functions are evaluated, and the return value is what gets injected.

Using a Resolve

Notice that we can inject into the resolve

$stateProvider
  .state('todos', {
    url: '/',
    controller: "TodosController",
    templateUrl: "templates/index.html",
    resolve: {
      TodoData: function(TodoService) {
        return TodoService.getTodos();
      }
    }        
});
app.controller("TodosController", 
function($scope, TodoData){
  $scope.todos = TodoData;
});

If your resolve is a function, you can use dependency injection just like it were a controller or service.

Using a Resolve

Returning promises is a great use of Resolve

$stateProvider
  .state('todos', {
    url: '/',
    controller: "TodosController",
    templateUrl: "templates/index.html",
    resolve: {
      TodoData: function(TodoService) {
        return TodoService.getTodos();
      }
    }        
});
app.controller("TodosController", 
function($scope, TodoData){
  $scope.todos = TodoData;
});

TodoService.getTodos() returns a promise. In our controlelr TodoData is the value of the resolved promise

Using a Resolve

If the resolve is a string it must be the name of a service

$stateProvider
  .state('todos', {
    url: '/',
    controller: "TodosController",
    templateUrl: "templates/index.html",
    resolve: {
      TodoData: 'TodoService'
    }        
});
app.controller("TodosController", 
function($scope, TodoData, TodoService){
  TodoService === TodoData; // true
});

I don't find this to be as useful, since you can easily inject services directly into your controller.

Questions?

Can You Attempt the Objectives?

  • Describe the function of a resolve
     

  • Use a resolve to inject data into a controller

Checkout this example, and try the challenge:

https://github.com/gSchool/angular-curriculum/tree/master/Unit-3/examples/ui_router_crud_resolves

Made with Slides.com