1

In my angularJs app I'm able to get $routeParams in the controller but how should I get it in a service? I would like to follow the separation of concerns approach and keep my http requests separate from my controllers.

I've tried the below in my app.js but I get a Error: $injector:unpr Unknown Provider

var app = angular.module('app', ['ngRoute']);  // TODO: 'ngAnimate', 'ui.bootstrap' 

app.config(['$routeProvider','$locationProvider', function($routeProvider, $locationProvider){

    $routeProvider
        .when('/', {
            templateUrl: '/app/static/home.html',
            controller: 'mainController as mainCtrl'

        })
        .when('/match/id-:matchId', {
            templateUrl: '/app/components/match/matchView.html',
            controller: 'matchController as matchCtrl'
        });

    // use the HTML5 History API
    $locationProvider.html5Mode(true);
}]);

app.controller('matchController', ['$routeParams', 'matchService', function ($routeParams, matchService) {
    var matchCtrl = this;
    matchCtrl.matchId = $routeParams..matchId;  // how can I move this into the service

    this.getMatchId = function ()
    {
        return matchCtrl.matchId;
    };

    var promise = matchService.getMatch();
    promise.then(function (data)
    {
        matchCtrl.match = data;
    });
}])

app.service("matchService", function ($http, $q, matchController)
{
    var matchId = matchController.getTable();

    var url = 'https://jsonplaceholder.typicode.com/posts/1';
    $http({
        method: 'GET',
        cache: true,
        url: url,
        headers: {  
           'Content-Type': 'application/json;charset=UTF-8'  
        }
    }).
    success(function(response) {
        //your code when success
        // lgTblCtrl.amateurTable = data;
        deferred.resolve(response);
        console.log('SUCCESS!');
    }).
    error(function(response) {
        //your code when fails
        console.log('ERROR!');
    });

    this.getTable = function ()
    {
        return deferred.promise;
    };
})
Aruna
  • 11,959
  • 3
  • 28
  • 42
Holly
  • 7,462
  • 23
  • 86
  • 140

1 Answers1

1

First of all, you have created cyclic reference where the matchService is injected into the matchController and matchController is injected into the matchService.

Service is a singleton object, created once which is the same instance passed wherever it gets injected. On contrast, controller will be created one per view. So if you have two views using the same controller, separate controller instances will be created and used by them by not sharing the $scope. So, if you inject a controller to the service, again another instance will be created and injected to the service.

Since a service should be generic and independent of the controller, you should not inject controller to any service as per the best coding practice.

Also, as a service is singleton and can be used by any controller or view, it should be independent to the view/route and hence you can't use $routeParams inside the service.

Instead, you can pass the $routeParams.matchId as an argument to the service method.

Note: In your controller, you have used $routeParams..matchId with double dots (..) instead of $routeParams.matchId.

Also, there is no matchService.getMatch inside the matchService which used by the controller.

You have to correct them.

I have changed the code below as I explained and have a look.

var app = angular.module('app', ['ngRoute']);  // TODO: 'ngAnimate', 'ui.bootstrap' 

app.config(['$routeProvider','$locationProvider', function($routeProvider, $locationProvider){

    $routeProvider
        .when('/', {
            templateUrl: '/app/static/home.html',
            controller: 'mainController as mainCtrl'

        })
        .when('/match/id-:matchId', {
            templateUrl: '/app/components/match/matchView.html',
            controller: 'matchController as matchCtrl'
        });

    // use the HTML5 History API
    $locationProvider.html5Mode(true);
}]);

app.controller('matchController', ['$routeParams', 'matchService', function ($routeParams, matchService) {
    var matchCtrl = {};

    var promise = matchService.getMatch($routeParams.matchId);
    promise.then(function (data)
    {
        matchCtrl.match = data;
    });
}])

app.service("matchService", function ($http, $q)
{
    var deferred = $q.defer();

    function getMatch(matchId) {
      var url = 'https://jsonplaceholder.typicode.com/posts/1';
      return $http({
        method: 'GET',
        cache: true,
        url: url,
        headers: {  
           'Content-Type': 'application/json;charset=UTF-8'  
        }
      }).
      then(function(response) {
        //your code when success
        // lgTblCtrl.amateurTable = data;
        deferred.resolve(response);
        console.log('SUCCESS!');
      }, function(response) {
        //your code when fails
        console.log('ERROR!');
        deferred.reject(response);
      });

      return deferred.promise;
    }

    this.getMatch = getMatch;
})
Aruna
  • 11,959
  • 3
  • 28
  • 42
  • thanks that makes sense but I still can't get it working with what you put above. There are no errors in the console, but when I put breakpoints in the Chrome Source panel I see it breaks on `this.getMatch = getMatch` before any of the `promise` or `deferred` statements. When it breaks on `deferred.resolve(response);` I can see the data in the `response` but it doesn't get passed in `matchCtrl.match = data` – Holly Dec 08 '16 at 10:01
  • I will create a sample app and look at it shortly. – Aruna Dec 08 '16 at 10:06
  • I got it working with https://gist.github.com/anonymous/8c8eeec87d3b40bdbcae7c640a82ab81, What do you think, it seems to be working well. If you add/include it in your answer I'll mark it as correct. Thanks so much for your help :) – Holly Dec 08 '16 at 10:39
  • yeah that's correct. This was `return deferred.promise` missed out. I have updated the answer. Thanks for letting me know :-) – Aruna Dec 08 '16 at 10:42
  • if you have time to look at http://stackoverflow.com/q/41025101/1814446 I'd really appreciate it. I would owe you a beer! – Holly Dec 08 '16 at 13:22