I'm currently working on a web app that uses Django REST Framework for the back end and AngularJS for the front end. I'm still fairly new to Angular and I'm struggling to get the list of projects to resolve before the page finishes rendering. Whenever the page loads, the Chromeconsole reports the following error:
Error: [$injector:unpr] Unknown provider: projectsProvider <- projects <- HomeCtrl
http://errors.angularjs.org/1.4.2/$injector/unpr?p0=projectsProvider%20%3C-%20projects%20%3C-%20HomeCtrl
at REGEX_STRING_REGEXP (http://127.0.0.1:8000/static/bower_components/angular/angular.js:68:12)
at http://127.0.0.1:8000/static/bower_components/angular/angular.js:4264:19
at Object.getService [as get] (http://127.0.0.1:8000/static/bower_components/angular/angular.js:4411:39)
at http://127.0.0.1:8000/static/bower_components/angular/angular.js:4269:45
at getService (http://127.0.0.1:8000/static/bower_components/angular/angular.js:4411:39)
at Object.invoke (http://127.0.0.1:8000/static/bower_components/angular/angular.js:4443:13)
at ident.$get.extend.instance (http://127.0.0.1:8000/static/bower_components/angular/angular.js:9001:34)
at nodeLinkFn (http://127.0.0.1:8000/static/bower_components/angular/angular.js:8111:36)
at compositeLinkFn (http://127.0.0.1:8000/static/bower_components/angular/angular.js:7543:13)
at publicLinkFn (http://127.0.0.1:8000/static/bower_components/angular/angular.js:7418:30) <div ng-view="" class="ng-scope">
Here's the routes:
var app = angular.module('projectile', [
'ngRoute',
'btford.markdown',
'projectile.controllers',
'projectile.services'
])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: '/static/templates/home.html',
resolve: {
projects: function (MultiProjectLoader) {
return MultiProjectLoader();
}
},
controller: 'HomeCtrl'
})
.otherwise({
redirectTo: '/'
});
});
Here's the controllers:
angular.module('projectile.controllers', [
'projectile.directives',
'projectile.services',
'ngRoute',
'btford.markdown'
])
.controller('HomeCtrl', function ($scope, projects, Issue) {
// Get open issues
$scope.issues = Issue.query({ open: true });
// Get projects
$scope.projects = projects;
});
Here's the services:
angular.module('projectile.services', ['ngResource'])
.factory('Project', function ($resource) {
return $resource('/api/projects/:projectId');
})
.factory('MultiProjectLoader', function (Project, $q) {
return function() {
var delay = $q.defer();
Project.query(function(projects) {
delay.resolve(projects);
}, function() {
delay.reject('Unable to fetch projects');
});
return delay.promise;
};
});
What's gone wrong? And how do I resolve it? If I use debugger
inside the controller, projects
is defined and contains the correct data, so I'm rather stumped.
I can just pass through Project
and run Project.query()
to get the result, but that means the page gets updated after it's rendered. I have a spinner directive in place and I want to wait for the request to finish before rendering the page, which I understand resolve
is for.
As your factory directly returning a promise, you should not call the function MultiProjectLoader
factory. Instead you should only return promise from the resolve function.
projects: function (MultiProjectLoader) {
//removed function bracket
return MultiProjectLoader; //returned the promise directive from resolve.
}
But as singleton is considered you shouldn't define factory this way. You should return object from factory and that will have various method which will used for different purpose.
Factory
.factory('MultiProjectLoader', function(Project, $q) {
return {
projectQuery: function() {
return roject.query().$promise.then(function(projects) {
return projects;
}, function(error) {
return error;
});
};
}
});
Resolve
projects: function (MultiProjectLoader) {
return MultiProjectLoader.projectQuery(); //returned the promise
}