I'm having trouble finding what's wrong in my code.
so, i'm resolving an http.get with ui-route and then calling the controller.
Elsewhere it works fine, but in a particular controller it don't
So, in my route.js i have this
.state('post', {
url: '/post/{id}',
templateUrl: 'post.php',
resolve: {
post: ['$http','$stateParams', function($http, $stateParams) {
return $http.get('link' + $stateParams.id)
.then(function(data) {
return data.data; });
}]
},
controller: 'PostController',
})
and the, in my controller i have this:
App.controller('PostController',['$scope', 'post', function PostController($scope, post) {
$scope.posts = post;
}]);
i get as i said an injection problem on post [$injector:unpr] (Unknown provider: postProvider <- post <- PostController), but i can see the http.get data in my controller. What am i missing?
Related
I have configure my MongoDb and API REST and when i tried to connect it with my Angular application i think it can't resolve.
I m learning MEAN application on this tutorial.
This is my ui-router configuration.
var app = angular.module('flapperNews', ['ui.router']);
app.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider,$urlRouterProvider){
$stateProvider
.state('home',{
url: '/home',
templateUrl: '/home.html',
controller: 'MainCtrl',
resolve: {
postPromise: ['posts',function(posts){
return posts.getAll();
}]
}
})
.state('posts',{
url: '/posts/{id}',
templateUrl: '/posts.html',
controller: 'PostCtrl'
});
$urlRouterProvider.otherwise('home');
}
]);
And this one is my factory.
app.factory('posts', ['$http',function (){
var o = {
getAll: function(){
return $http.get('/posts').success(function(data){
angular.copy(data,o.posts);
});
}
};
return o;
}]);
And this is the return of /posts
curl http://localhost:3000/posts/
[{"_id":"564f63d0e1f4efce4e36d863","name":"test","link":"http://test.com","__v":1,"comments":["564f70adf3340cab52f9d117"],"upvotes":2}]
The result is a white page whitout error.
Can you help me ?
Inject $http in your factory like below.
app.factory('posts', ['$http',function ($http){ your code }])
The issue that you have here is with the $http service in your factory. You need to inject it in the function, like this:
app.factory('posts', ['$http',function ($http){
var o = {
getAll: function(){
return $http.get('/posts').success(function(data){
angular.copy(data,o.posts);
});
}
};
return o;
}]);
It the rest of the code is fine, it should work without any issues. Here is one modified and simplified plunker that usses $q to return a promise instead of the $http since I don't have an http endpoint to call.
One error I see is that you haven't returned a promise in your resolve. getAll() uses an async api and thus you will have to return a promise. So change
posts.getAll();
to
posts.getAll().then(function(data) {
return data.data;
})
in your resolve. However, I am not sure if this will solve your problem completely.
I have a api that i want to resolve name for "bubble". This i would like to inject into controller - but problem is that i have tried different approaches and all just say...undefined and some injection problems... :(
Code:
.state('bubbles', {
abstract: false,
url: "/bubbles/:bubbleId/feed",
controller: 'BubblesController',
data: {
authorizedRoles: [USER_ROLES.editor]
},
resolve: {
resolvedBubbleName: function ($http, $stateParams) {
var url = 'https://XXXXXXX.net/api/Bubble/11111111-1111-1111-1111-111111111111';
return $http.get(url)
.then(function (response) {
console.log('response ' + response);
return response;
});
},
views: {
'navigation': {
templateUrl: "/raqt/shared/partials/navigation.html"
},
'main': {
templateUrl: "/raqt/bubbles/partials/bubbles.html"
//controller: function ($scope, resolvedBubbleName) {
// $scope.resolvedBubbleName = resolvedBubbleName;
// // resolvedBubbleName is always undefined, i.e.,
// // UI router is not injecting it
//}
}
},
}
})
In my controller i tried different approaches and this that i think should work... gives error injection...
BubblesController.$inject = ['$stateParams', '$state', '$log', '$timeout', '$interval', '$scope', 'BubblesService', 'CONFIG', '$http', 'resolvedBubbleName'];
function BubblesController($stateParams, $state, $log, $timeout, $interval, $scope, BubblesService, CONFIG, $http, resolvedBubbleName) {
$scope.title = 'bubbles-controller';
alert(resolvedBubbleName);
$scope.bubbleId = $state.params.bubbleId;
Error from page
Error: [$injector:unpr] Unknown provider: resolvedBubbleNameProvider <- resolvedBubbleName <- BubblesController
http://errors.angularjs.org/1.3.15/$injector/unpr?p0=resolvedBubbleNameProvider%20%3C-%20resolvedBubbleName%20%3C-%20BubblesController
at REGEX_STRING_REGEXP (http://localhost:3604/js/lib/angular/angular.js:63:12)
at http://localhost:3604/js/lib/angular/angular.js:4015:19
at Object.getService [as get] (http://localhost:3604/js/lib/angular/angular.js:4162:39)
at http://localhost:3604/js/lib/angular/angular.js:4020:45
at getService (http://localhost:3604/js/lib/angular/angular.js:4162:39)
at Object.invoke (http://localhost:3604/js/lib/angular/angular.js:4194:13)
at $get.extend.instance (http://localhost:3604/js/lib/angular/angular.js:8493:21)
at http://localhost:3604/js/lib/angular/angular.js:7739:13
at forEach (http://localhost:3604/js/lib/angular/angular.js:331:20)
at nodeLinkFn (http://localhost:3604/js/lib/angular/angular.js:7738:11) <div ui-view="main" class="ng-scope">
I can see that $http call is having data and i know controller works well otherwise - but this resolve driving me mad.. :(
I will be off for couple of hours - but i WILL ge back to this if you see some problems in my code i will ge back and answer!... :)
I would say, that you've wrongly nested views : {} into the resolve : {}. There is a working plunker
I just moved your definitions into correct positions and it is working
.state('bubbles', {
abstract: false,
url: "/bubbles/:bubbleId/feed",
//controller: 'BubblesController',
data: {
authorizedRoles: [{}], //USER_ROLES.editor]
},
resolve: {
resolvedBubbleName: ['$http', '$stateParams',
function($http, $stateParams) {
//var url = 'https://XXXXXXX.net/api/Bubble/11111111-1111-1...';
var url = 'someData.json'
return $http.get(url)
.then(function(response) {
console.log('response ' + response);
return response.data;
});
}
],
},
views: {
'navigation': {
templateUrl: "raqt/shared/partials/navigation.html",
controller: 'BubblesController',
},
'main': {
templateUrl: "raqt/bubbles/partials/bubbles.html",
controller: ['$scope', 'resolvedBubbleName',
function($scope, resolvedBubbleName) {
$scope.resolvedBubbleName = resolvedBubbleName;
}
]
}
},
})
Also, one very important note:
controller belongs to view - not to state
You can read more here:
Are there different ways of declaring the controller associated with an Angular UI Router state
Check the working example here
EXTEND
In case, that we adjusted all the code as above and we are provided with this error:
Error: [$injector:unpr] Unknown provider: resolvedBubbleNameProvider <- resolvedBubbleName <- BubblesController
We are most likely in one of these scenarios:
we have elsewhere in our state hierarchy reused the "BubblesController", while not having resolve : { 'resolvedBubbleName': ... } in place
we declared somewhere ng-controller="BubblesController" - which is not managed by UI-Router. And it does not have access to so called locals (containing resolved values)
so, be sure where is the controller defined - all will start working then...
I am a bit confused. I am trying to get my resolve data in my controller. I read about these (and more) solutions, but can not get it working. It is all about the "spages".
http://jsfiddle.net/Avb4U/1/
http://www.jvandemo.com/how-to-resolve-angularjs-resources-with-ui-router/#
Angularjs resolve with controller as string
I hope this is not a duplicate question, because nothing did work for me from these solutions.
This is (part of all states) my state:
.state('root.search', {
url: '/search/:searchterm',
onEnter: ['$rootScope', function($rootScope) {
$rootScope.bodyclass = 'search';
}],
resolve : {
spages: ['$stateParams', 'SearchPages', function($stateParams, SearchPages) {
return SearchPages.get({'searchterm': $stateParams.searchterm});
}]
},
controller: 'searchCtrl',
views: {
'#': {
templateUrl: templateUrlFunction('search')
}
}
})
This is part of my controller:
app.controller('searchCtrl', ['$scope', 'spages', function($scope, spages) {
// spages should be already resolved and injected here
}
And this is my factory for the searchpages:
app.factory('SearchPages', ['$resource', function($resource) {
return $resource(null, {},
{
get: {
method: 'GET',
url: '/json/search/get/searchterm/:searchterm',
params: {searchterm: '#searchterm'}
}
});
}]);
Asfar as i do understand, spages should be resolved and injected in the controller now. But it is not.
The error i get is:
Error: [$injector:unpr] Unknown provider: spagesProvider <- spages
What do i do wrong? I am still learning...
Ok, what i did not realize is that i also have a controller in my template.
And i read: "You only need to specify controller once, in app.js. The second one, in the html code, is instantiated by the ngController directive, which does not know about `resolve', so it throws an exception."
Change your controller dependency from searchpages to SearchPages.
app.controller('searchCtrl', ['$scope', 'SearchPages', function($scope, searchpages) {
// searchpages should be already resolved and injected here
}
I am continuing to have issues where my templates and directives are throwing errors because they are trying to be $compiled before the data is actually set. This is because it takes time for the API response to get back.
Therefore, I am trying to convert my API call to work in the resolve property of my route, however I cannot figure out how to do it correctly. Here is what I have:
My State Provider w/ resolve property
$stateProvider
.state('dashboard', {
url: '/',
controller: 'LandingController',
resolve: {
data: ['API', function(API){
return API.Backups.getAll(function (data) {
return data.result;
});
}]
}
})
My controller
app.controller('LandingController', ['$scope', 'API', function ($scope, API, data) {
$scope.data = data;
......
I am using an Angular service that provides a $resource in order to get the API data, however something is not working still because my data parameter in the controller is still undefined.
I figured out what I needed. I just needed to return the $resource.$promise instead of just the $resource. After doing that, everything worked great!
Solution
$stateProvider
.state('dashboard', {
url: '/',
controller: 'LandingController',
resolve: {
res: ['API', function(API){
return API.Backups.getAll(function (data) {
return data.result;
}).$promise;
}]
}
})
Without the code for API.Backups.getAll() I can't tell, but the resolve function needs to return a "promise" which can be provided by the Angular $q:
resolve: ['$q', 'API', function($q, API) {
// 1. $q provides the deferred which satisfies the "promise" API
var deferred = $q.defer();
// 2. call your API
API.Backups.getAll(function (data) {
// 4. resolve the promise with data that was returned
deferred.resolve(data.result);
});
// 3. return the promise
return deferred.promise;
}]
The numbered comments show the order things will occur. Angular will not instantiate your controller until resolve() is called on the promise (deferred).
see: https://docs.angularjs.org/api/ng/service/$q
I am trying to do an asynchronous http request to load some data before my app loads and so I am using a resolve in $routeProvider which is an http request in my MainController. For some reason, I keep getting Error: [$injector:unpr] Unknown provider: appDataProvider <- appData where appData is where I do my http request. I am using AngularJS v 1.2.5.
Here is the code and two methods that I tried that both give the same error:
Method #1
MainController.js
var MainController = ['$scope','$location','appData',
function($scope, $location, appData){
console.log(appData.data);
}
];
MainController.loadData = {
appData: function($http, $location, MainFactory){
var aid = MainFactory.extractAid($location);
return $http({method: 'GET', url: URL_CONST + aid});
}
};
app.js
var app = angular.module('HAY', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
redirectTo: '/pages/alerts'
})
.when('/pages/:pageName', {
templateUrl: function(params) {
return 'views/pages/' + params.pageName + '.html';
},
controller: MainController,
resolve: MainController.loadData
})
.otherwise({
redirectTo: '/pages/alerts'
});
});
I tried changing the name in case it was a conflicting system reserved keyword but with no luck. For some reason, appData is never recognized
Method #2
I also tried changing it around like so:
app.js
var app = angular.module('HEY', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
redirectTo: '/pages/alerts'
})
.when('/pages/:pageName', {
templateUrl: function(params) {
return 'views/pages/' + params.pageName + '.html';
},
controller: MainController,
resolve: {
appData: ['$http', '$location','MainFactory', function($http, $location, MainFactory) {
var aid = MainFactory.extractAid($location);
return $http({method: 'GET', url: URL_CONST + aid});
}]
}
})
.otherwise({
redirectTo: '/pages/alerts'
});
});
MainController.js
var MainController = ['$scope','$location','appData',
function($scope, $location, appData){
console.log(resolvedData);
}
];
However, the result was exactly the same. Does this have something to do with angular 1.2.5 ?
Here is a working version from someone else
http://mhevery.github.io/angular-phonecat/app/#/phones
And here is the code:
function PhoneListCtrl($scope, phones) {
$scope.phones = phones;
$scope.orderProp = 'age';
}
PhoneListCtrl.resolve = {
phones: function(Phone) {
return Phone.query();
},
delay: function($q, $defer) {
var delay = $q.defer();
$defer(delay.resolve, 1000);
return delay.promise;
}
}
angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl, resolve: PhoneListCtrl.resolve}).
otherwise({redirectTo: '/phones'});
}]);
Here's an example of the code I've used in the application I'm working on, not sure it will help much because its not much different than how you have it already.
Routing
.when('/view/proposal/:id',{
controller : 'viewProposalCtrl',
templateURL : 'tmpls/get/proposal/view',
resolve : viewProposalCtrl.resolveViewProposal
})
Controller
var viewProposalCtrl = angular.module('proposal.controllers')
.controller('viewProposalCtrl',['$scope','contacts','details','rationale',
function($scope,contacts,details,rationale){
$scope.contacts = contacts;
$scope.details = details;
$scope.rationale = rationale;
// [ REST OF CONTROLLER CODE ]
});
// proposalSrv is a factory service
viewProposalCtrl.resolveViewProposal = {
contacts : ['$route','proposalSrv',function($route,proposalSrv){
return proposalSrv.get('Contacts',$route.current.params.id)
.then(function(data){
return data.data.contacts;
},function(){
return [];
});
}],
details : ['$route','proposalSrv',function($route,proposalSrv){
return proposalSrv.get('Details',$route.current.params.id)
.then(function(data){
return data.data.details;
},function(){
return {};
});
}],
rationale : ['$route','proposalSrv',function($route,proposalSrv){
return proposalSrv.get('Rationale',$route.current.params.id)
.then(function(data){
return data.data.rationale;
},function(){
return {};
]
}]
};
Now that I think about it, when I was developing my application I did have a problem and not sure why when I named my resolve function "resolve." This gave me a problem:
.when('/path',{
// stuff here
resolve : myCtrlr.resolve
})
but this did not:
.when('/path',{
//stuff here
resolve : myCtrlr.myResolveFn
})
Another Possibility
The only other thing I can think of, is that you're returning the promise from the $http call and then trying to use appData.data Try using the .then function or one of the other functions (.success,.error) to retrieve the information from the promise.
The problem was NOT due to previously using different version of AngularJS.
Here are the fixes using the code that I have above.
In app.js, you need to declare the controller as controller: 'MainController' and NOT as controller: MainController even though you have var MainController = app.controller('MainController', ....).
Second and biggest thing was that in my index.html I declared my controller already like so:
index.html
body ng-app="HEY" controller="MainController" /body
This was causing the whole Unknown provider error Apparently angular wont tell you that you have already declared the controller that you are using to do the resolve it and that that will cause a weird error that have nothing to do with the resolve.
I hope this helps someone who may have the same problem.
One thing I noticed in angular 1x docs is that YOU DO NOT SPECIFY THE RESOLVED PARAMETER AS AN ANNOTATED DEPENDENCY
So this:
.when('/somewhere', {
template: '<some-component></some-component>',
resolve: {
resolvedFromRouter: () => someService.fetch()
}
})
export default [
'$scope',
'someService',
'resolvedFromRouter'
Controller
]
function Controller($scope, someService, resolvedFromRouter) {
// <= unknown provider "resolvedFromRouter"
}
is wrong. You don't specify the resolved parameter as a dependency, in the docs:
For easier access to the resolved dependencies from the template, the resolve map will be available on the scope of the route, under $resolve (by default) or a custom name specified by the resolveAs property (see below). This can be particularly useful, when working with components as route templates.
So just do this instead:
.when('/somewhere', {
template: '<some-component></some-component>',
resolve: {
resolvedFromRouter: () => someService.fetch()
}
})
export default [
'$scope',
'someService',
Controller
]
function Controller($scope, someService) {
$scope.$resolve.resolvedFromRouter; // <= injected here
}