angularjs change rootscope after promise in a controller

690 views Asked by At

I'm trying to change some $rootscope variables from within a controller after a I have received a promise from a service.

The $rootscope variables are used to set the html page title attribute etc.

Below is the code I have, I created a function called changeRootPageNotFound() to change the $rootscope variables. It does not work if it's called in the promise.then function.

app.controller('mainController', ['$routeParams', '$scope', '$rootScope', 'mainService', function ($routeParams, $scope, $rootScope, mainService) {
    var mainCtrl = this;
    mainCtrl.id = $routeParams.itemId;

    var promise = mainService.getData($routeParams.id);

    promise.then(function (response)
    {
        if (response.data.data) {
            mainCtrl.data = response.data.data;
        } else {
            mainCtrl.data = false;
            changeRootPageNotFound();
        }
    });
    function changeRootPageNotFound() {
        $rootScope.title = "Page Not Found - 404";
        $rootScope.titleSuffix = "";
    }
    // changeRootPageNotFound();  // works here
}]);

How can I change the $rootscope variables after I have received the deferred promise from the service?

2

There are 2 answers

2
georgeawg On BEST ANSWER

Add a .catch method:

promise.then(function (response)
{
    //if (response.data.data) {
        mainCtrl.data = response.data.data;
    //} else {
    //    mainCtrl.data = false;
    //    changeRootPageNotFound();
    //}
}).catch(function(errorResponse) {
    console.log(errorResponse.status);
    mainCtrl.data = false;
    changeRootPageNotFound();
    throw errorResponse;
});

The $http service rejects the promise when the status is outside the range 200-299.


What is the throw errorResponse; for, can it be left out?

If the throw errorResponse is omitted, the rejection handler returns a value of undefined. This will convert the rejected promise to a fulfilled promise that resolves as undefined. If there is no further chaining, it can be left out.

A common cause of problems is programmers being unaware of this and unintentionally converting promises.


instead of .catch you can pass the same function to then as the 2nd argument

One of the subtle differences between .catch and using the 2nd argument of the .then method, is that runtime errors in the .then success handler will not be caught in the rejection handler of the 2nd argument.

0
John Maclein On

According to your snippet your code should have worked. In my plunker its working after the deferred promise also.

// Code goes here
angular.module('Test',[])
  .service('Service', function($q){
    this.ts = function(){
      var deferred = $q.defer();
      deferred.resolve("hello")
      return deferred.promise;
    }
  })
  .controller('Controller', function(Service, $rootScope){

    Service.ts().then(function(response){
      $rootScope.title="hello";
      changeRootPageNotFound();
    });

    function changeRootPageNotFound() {
        $rootScope.title = "Page Not Found - 404";
        $rootScope.titleSuffix = "";
    }
  });

Here is the html

<!DOCTYPE html>
<html>

  <head>
    <script data-require="[email protected]" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app="Test">
    <div ng-controller="Controller">

      <h1>{{title}}</h1>

    </div>
  </body>

</html>

Please check this Plunker https://plnkr.co/edit/THXDYrWuTqR8UYSJlerB?p=preview