I following thinkster MEAN stack tutorial and I have a problem in angular factory service
angular.js:11598 Error: [$rootScope:infdig] 10 $digest() iterations
reached. Aborting! Watchers fired in the last 5 iterations: []
app.js
app.factory('posts', ['$http', function($http){
var o = {
posts: []
};
o.getAll = function() {
return $http.get('/posts').success(function(data){
console.log(data)
angular.copy(data, o.posts);
});
};
return o;
}]);
my config file has route provider
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home.html',
controller: 'MainCtrl',
resolve: {
post: ['$stateParams', 'posts', function($stateParams, posts) {
return posts.get($stateParams.id);
}]
}
})
Im not sure what is wrong..
Any help is much appreciated. Thanks in advance...
.successis deprecated so i will use then
I think this is what you wanted to write.
app.factory('posts', ['$http', function($http){
var o = {};
o.get = function(id){
return $http.get('/posts/'+id).then(function(response){
return response.data;
});
}
o.getAll = function() {
return $http.get('/posts').then(function(response){
return response.data;
});
};
return o;
}]);
resolve: {
post: ['$stateParams', 'posts', function($stateParams, posts) {
return posts.get($stateParams.id);
}]
}
// usage of the factory in controller :
posts.getAll().then(function(posts){
$scope.allPosts = posts;
})
posts.get(id).then(function(post){
$scope.post = post;
})
Some points :
then/ successare chainable; however you must use the return statement in order than the next chain will have the data. I will have what you have returned.
I totally don't know from where you got your return posts.get($stateParams.id); so i added something relevant.
Related
Here is my code :
Js:
angular.module('main', [])
.config(['$locationProvider', '$routeProvider',
function($locationProvider, $routeProvider) {
$routeProvider.when('/tables/bricks', {
controller: "myController",
resolve: {
"check" : function($location){
if(!$scope.bricks) {
$route.reload();
}
}
},
templateUrl: 'tables/bricks.html'
});
$routeProvider.otherwise({
redirectTo: '/tables/datatables'
});
}
])
.controller('myController', function($scope, $location, $http) {
var vm = this;
$scope.Bricks = function(){
$location.path('/tables/bricks');
};
vm.getbricks = function(n){
var url = n;
$http({
method: 'GET' ,
url: url,
})
.then(function successCallback(data) {
$scope.bricks = data.data;
console.log($scope.bricks);
}, function errorCallback(response) {
console.log(response);
console.log('error');
});
};
});
HTML:
<button ng-click="vm.getbricks(n.bricks_url);Bricks();"></button>
After click the button in html, my page goes into /tables/bricks, but nothing happend, because resolve probably is wrong. What I want - that i could go to /tables/bricks only then, when $scope.bricks exist, so only when vm.bricks() will be called.
Thanks for answers in advance!
I think your problem is that the vm.getbricks will always return something (in success or error handler), so will never be falsy, and you will always call the Bricks() constructor. try to return true on success callback and false in error callback.
$scope is for controllers, which it can't reach in the config. Instead, you should be returning something from a service, which will be called during your resolve. E.g. if(YourService.getbricks())
Solution: move your logic from a controller into a service. And make sure to return a value from it that can be checked in the config.
app.service('BrickService', function() {
this.getbricks = function(url) {
return $http.get(url) // return the Promise
.then(function(response) {
return response.data; // return the data
}, function(error) {
console.log(error);
});
};
});
With this you can inject the service into the config and run its function.
angular.module('main', [])
.config(['$locationProvider', '$routeProvider',
function($locationProvider, $routeProvider) {
$routeProvider.when('/tables/bricks', {
controller: "myController",
resolve: {
"check": function(BrickService) { // inject
if ( BrickService.getbricks() ) { // run its function
$route.reload();
}
}
},
templateUrl: 'tables/bricks.html'
});
$routeProvider.otherwise({
redirectTo: '/tables/datatables'
});
}
])
You can also use the loaded values in the controller after they have been resolved. For that, you would need to simply return it. So change the logic to this:
resolve: {
"check": function(BrickService) { // inject
var bricks = BrickService.getbricks(); // run its function
if ( bricks ) {
$route.reload();
}
return bricks; // return the result (note: it's not a Promise anymore)
}
}
Then you can inject this resolve into your controller:
.controller('myController', function($scope, $location, $http, check) {
var vm = this;
vm.bricks = check;
...
(Note check was added)
I'm trying to do a simple app with ionic framework to learn how to use Firebase and manipulate data. I did everything, but my console is showing nothing. I cannot run my controller. Does anyone know what is happening?
I injected everything, at least I think I did. I guess the error is in the resolve. Is there anyone that can save me with this, please?
Here's my Controller:
(function(){
'use strict';
angular
.module('hsAdmin.users')
.controller('UsersCtrl', UsersCtrl);
UsersCtrl.$inject = ['$scope', '$state','Users' ];
function UsersCtrl($scope, $state,Users ){
var vm = angular.extend(this, {
ChangeState: ChangeState,
Users:Users
});
function ChangeState(state){
$state.go(state);
}
}
})();
Here's my Module:
(function(){
'use strict';
angular
.module('hsAdmin.users', [
'ionic',
'ngCordova',
'hsAdmin.users'
])
.config(function($stateProvider) {
$stateProvider
.state('app.users', {
url: '/users',
views: {
'menuContent': {
templateUrl: 'templates/users/users.html',
controller: 'UsersCtrl as vm'
}
}
,resolve:{
Users: function(UsersService) {
return UsersService.GetUsers().$loaded().then(function(user){
return user;
}).catch(function(error){
console.log('Error when get users: ' + error);
})
}
}
});
})
})();
Here's my Service
(function(){
'use strict';
angular
.module('hsAdmin.users')
.factory('UsersService', UsersService);
UsersService.$inject = ['fb', '$firebaseArray', '$firebaseObject','$q','$rootScope'];
function UsersService(fb, $firebaseArray, $firebaseObject,$q,$rootScope){
var service = {
GetUsers:GetUsers,
GetUsersById:GetUsersById
};
return service;
function GetUsers(){
var query = fb.child('/users');
return $firebaseArray(query);
}
function GetUsersById(id){
var query = fb.child('/users/' + id);
return $firebaseObject(query).$loaded();
}
}
})();
You are creating your hsAdmin.users module and then injecting it into itself, that is likely what is causing your problem. Try the below:
(function(){
'use strict';
angular
.module('hsAdmin.users', [
'ionic',
'ngCordova',
// 'hsAdmin.users'
])
.config(function($stateProvider) {
$stateProvider
.state('app.users', {
url: '/users',
views: {
'menuContent': {
templateUrl: 'templates/users/users.html',
controller: 'UsersCtrl as vm'
}
}
,resolve:{
Users: function(UsersService) {
return UsersService.GetUsers().$loaded().then(function(user){
return user;
}).catch(function(error){
console.log('Error when get users: ' + error);
})
}
}
});
})
})();
Try to implement controller in following way.
(function() {
'use strict';
var UsersCtrl = function($scope, $state, Users) {
var vm = angular.extend(this, {
ChangeState: ChangeState,
Users: Users
});
function ChangeState(state) {
$state.go(state);
}
}
UsersCtrl.$inject = ['$scope', '$state', 'Users'];
angular.module('hsAdmin.users').controller('UsersCtrl', UsersCtrl);
})();
I'm new at Javascripts and i'm trying to use Angular UI route, here is my code
myApp.config(['$stateProvider', '$urlRouterProvider',function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/test',
templateUrl: '/custom.html'
})
.state('detail', {
url: '/{examID}',
views: {
'': {
templateUrl: '/templates/customize.html',
controller: ['$scope', '$stateParams', 'utils',
function ( $scope,$stateParams,utils) {
$scope.exam = utils.findById($stateParams.examID);
console.log('exam is ' + $scope.exam );
}
]
}
}
} )
}])
and this is the service which has findbyID function
angular.module('service', [])
.factory('utils', function ( $http) {
return {
findById: function findById(id) {
$http.get('/api/exams/' + id).success(function(response) {
return response;
})}
};});
i've already follwed this topic but $scope.exam still undefined
How to return value from an asynchronous callback function?
PS. i've tried to print out response and it's an object
Thx
This is a place where a lot of developers new to JavaScript stumble.
What is going on here is that you are assigning the return value of utils.findById() to $scope.exam. The problem is that utils.findById() doesn't actually return anything. (When a function doesn't have an explicit return statement in JavaScript, the return value is implicitly undefined.)
Here is what your service should look like:
angular
.module('service', [])
.factory('utils', function ($http) {
return {
findById: function (id) {
return $http.get('/api/exams/' + id);
}
};
});
You probably noticed that the call to .success() has disappeared too! Don't worry. It just moved.
Instead of calling .success() on $http.get(), we want to call it on utils.findById(). Doing this will give you access to the response variable in your controller. Because you will have access to the response variable, you will be able to assign response to $scope.exam like so:
.state('detail', {
url: '/{examID}',
views: {
'': {
templateUrl: '/templates/customize.html',
controller: ['$scope', '$stateParams', 'utils',
function ($scope, $stateParams, utils) {
utils.findById($stateParams.examID)
.success(function (response) {
$scope.exam = response;
});
}
]
}
}
});
Hopefully that cleared it up. If I haven't been clear on anything, please let me know so I can update this answer.
You have to wait for the ajax call to finish. Modify the code in your controller to:
$scope.exam;
utils.findById($stateParams.examID).then(function(data) {
$scope.exam = data.data;
}
Read about the concept of 'Promises' in AngularJS and JavaScript.
Use deferred promise, So that it would return value after response
Service:
angular.module('service', [])
.factory('utils', function ( $http) {
return {
findById: function findById(id) {
var promise=$http.get('/api/exams/' + id);
return promise;
};});
Controller:
myApp.config(['$stateProvider',
'$urlRouterProvider',function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/test',
templateUrl: '/custom.html'
})
.state('detail', {
url: '/{examID}',
views: {
'': {
templateUrl: '/templates/customize.html',
controller: ['$scope', '$stateParams', 'utils',
function ($scope, $stateParams, utils) {
utils.findById($stateParams.examID).then(function(value) {
$scope.exam = value;
console.log('exam is ' + $scope.exam );
});
}
]
}
}
})
}])
I'm running out of idea right now. Everything seems fine, but when Im trying to inherit master data into the details view nothing really shows when I consoled except for the id.
Console Output : Object {id: "78"}
Here's my code :
Config
.state('app.home', {
url: "/home",
views: {
'menuContent': {
templateUrl: "templates/home.html",
controller: 'PostHomeCtrl'
}
}})
.state('app.posthome', {
url: "/home/:id",
views: {
'menuContent': {
templateUrl: 'templates/post.html',
controller: 'PostDetailCtrl'
}
}})
Factory
.factory('Posts', function($http){
var blogs = []; //Private Variable
return {
GetBlog: function(){
return $http.get('path/to/resources').then(function(response){
blogs = response;
return response;
});
},
GetPost: function(postId){
for(i=0;i<blogs.length;i++){
if(blogs[i].id == postId){
return blogs[i];
}
}
return null;
}
}})
Controller
.controller('PostHomeCtrl', function(Posts, $scope){
Posts.GetBlog().then(function(blogs){
$scope.blogs = blogs.data;
console.log(blogs.data);
});
})
.controller('PostDetailCtrl', function(Posts, $stateParams, $scope){
var postId = $stateParams;
$scope.blog = Posts.GetPost(postId);
console.log(postId);
});
nvm just figured it out, turns out my I forgot to add .data at my blog = response . So it becomes blog=response.data instead of blog=response. Thanks
I am aware that the error which is in the title of this question is basically because in my controller I am injecting a Session service in my controller that has not been defined. I am currently looking at: Angular Devise for which I am rolling out in an application that is using rails but have angular and rails separate. My setup on the angular side is as followed:
main.js
angular.module('App.controllers', []);
angular.module('App.config', []);
angular.module('App.directives', [])
angular.module('App.resources', ['ngResource']);
angular.module('App.services', []);
var App = angular.module("App", [
"ngResource",
"ngCookies",
"$strap.directives",
"App.services",
"App.directives",
"App.resources",
"App.controllers",
"TotemApp.config"
], function ($routeProvider, $locationProvider, $httpProvider) {
var interceptor = ['$rootScope', '$q', function (scope, $q) {
function success(response) {
return response;
}
function error(response) {
var status = response.status;
if (status == 401) {
window.location = "/login";
return;
}
return $q.reject(response);
}
return function (promise) {
return promise.then(success, error);
}
}];
});
Session.js
App.service('Session',[ '$cookieStore', 'UserSession', 'UserRegistration', function($cookieStore, UserSession, UserRegistration) {
this.currentUser = function() {
return $cookieStore.get('_angular_devise_user');
}
this.signedIn = function() {
return !!this.currentUser();
}
this.signedOut = function() {
return !this.signedIn();
}
this.userSession = new UserSession( { email:"sample#email.com", password:"password", remember_me:true } );
this.userRegistration = new UserRegistration( { email:"sample#email.com", password:"password", password_confirmation:"password" } );
}]);
sessions_controller
App.controller('SessionsController', ['$scope', '$location', '$cookieStore', 'Session', function($scope, $location, $cookieStore, Session) {
$scope.session = Session.userSession;
$scope.create = function() {
if ( Session.signedOut ) {
$scope.session.$save().success(function(data, status, headers, config) {
$cookieStore.put('_angular_devise_user', Session.userSession.email);
$location.path('/todos');
});
}
};
$scope.destroy = function() {
$cookieStore.remove('_angular_devise_user');
$scope.session.$destroy();
};
}]);
routes.js
'use strict';
App.config(function($routeProvider, $httpProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main/home.html',
controller: 'MainCtrl'
})
.when('/login', {
templateUrl: 'views/sessions/new.html',
controller: 'SessionsController'
})
.when('/sign_up', {
templateUrl: 'views/registrations/new.html',
controller: 'RegistrationsController'
})
.otherwise({
redirectTo: '/'
});
});
This error occurs when I try to access the login page or register page. If someone can shed some light that would be greatly appreciated. Not entirely sure how to resolve this Error: Unknown provider: $SessionProvider <- $Session error
At first glance this looks correct. I can only assume that perhaps you've not included Session.js in your index.html file?
Angular clearly doesn't know what 'Session' service is so there's something wrong there either file not loaded, not loaded correctly or something along those lines as far as I can see.
Edit: Does the error say 'SessionProvider <- Session' or '$SessionProvider -< $session' because if it's the latter, then something is named wrong somewhere in your app since your service is named 'Session' not '$Session'.
When you have syntax error in other javascript or typescript files. You will get the same error. Please make sure that you have no syntax error.