I'm trying to send a receive a response from a server using ngResource module of Angular. I'm using promises but it doesn't work, I think there might be something wrong with my code. It goes as it is :
Controller:
var LoginController = angular.module('LoginController', [
]);
LoginController.controller("LoginController", ['$scope','$location','LoginService', function($scope, $location, LoginService) {
$scope.user = {}
$scope.checkCredentials = function () {
var userCredentials = LoginService.get();
userCredentials.$promise.then(function(result){
$scope.user.login = response.login;
$scope.user.password = response.password;
});
};
}]);
Rest module:
var RestServices = angular.module('RestServices', ['ngResource']);
RestServices.factory('LoginService', ['$resource','$routeParams',
function($resource, $routeParams){
return $resource('/user',{},{
get: {method:'GET', isArray:false}
});
}]);
If I put the line:
var userCredentials = LoginService.get();
directly inside declaration of controller, it works and object user is filled properly and send to my view, but when I try to do that in a function invoked by clicking a button (like it is in my code) it doesn't fill user object properly. What might be wrong with my code?
Thanks in advance.
Change "result" to "response"!
var userCredentials = LoginService.get();
userCredentials.$promise.then(function(response){
$scope.user.login = response.login;
$scope.user.password = response.password;
});
But you can also achieve the same in a more succinct and idiomatic way:
LoginService.get(function(data){
$scope.user.login = data.login;
$scope.user.password = data.password;
});
Related
Login.js:
app.controller('LoginFormController', ['$scope','$http','$rootScope', '$state', function($scope, $http, $rootScope, $state) {
$scope.user = {};
$scope.authError = null;
$scope.login = function() {
$scope.authError = null;
var emailId = $scope.user.email;
var password = $scope.user.password;
$http({
url: 'http://localhost:8090/login/login',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: 'email='+emailId+'&password='+password
//data: {'email': $scope.user.email, 'password': $scope.user.password}
}).then(function(response) {
console.log(response.data);
if (response.data.status == 'SUCCESS') {
$scope.user = response.data.user.firstName;
$rootScope.test = response.data.user.firstName;
console.log("check: ",$rootScope.test)
$state.go('app.dashboard');
} else {
//alert('invalid login');
$scope.authError = 'Email or Password not right';
}
}, function(x) {
$scope.authError = 'Server Error';
})
};
}])
I saved the value under $rootScope.test
Here Is my App.main.js:
'use strict';
angular.module('app').controller('AppCtrl', ['$scope','$rootScope',
function($scope, $rootScope) {
$scope.user5 = $rootScope.test;
}
]);
trying to print the rootscope
If I run this Code i am facing the error of $rootScope is undefined in the console. How to Resolve this
$rootScope is the parent of all $scope, each $scope receives a copy of $rootScope data which you can access using $scope itself.
Here is a modified version
https://jsfiddle.net/sedhal/g08uecv5/17/
angular.module('myApp', [])
.run(function($rootScope) {
$rootScope.obj = {
"name":"user1",
"bdate":"18/11/1994",
"city":"Ahmedabad"
};
})
.controller('myCtrl', function($scope, $rootScope) {
$scope.data = $rootScope.obj;
})
.controller('myCtrl2', function($scope, $rootScope) {
$scope.data1 = $rootScope.obj;
});
There is a useful answer to your question here: https://stackoverflow.com/a/18881189/9013688
Instead of passing directly your property on the $rootScope, you could emit an event which could be listened in an other part of your app like this:
if (response.data.status == 'SUCCESS') {
$rootScope.$emit('user-logged', response.data.user.firstName)
}
And then:
$rootScope.$on('user-logged', function(event, data){
do something with your data
})
Or you could use a service which is a good way to handle your data in all your app.
Please ensure that you take the advice of georgeawg, his suggestion seems to be the best way to implement this functionality in my opinion.
I want to suggest what might be wrong with your example.
If you can see that in the main App.main.js you have given the declaration as
angular.module('app').controller(...
But you are using a variable app in login.js like so.
app.controller(...
Which I am assuming you are creating somewhere else. Thus the set rootscope value is lost because there are two instances of the same app.
The solution to your problem will be to declare one variable app which will store the instance of the app. So the fix for your solution will be to modify App.main.js to be like so.
var app = angular.module('app');
app.controller(...
Also you need to remove any other arbitary var app = in your complete code, since these will create multiple instances of the same app.
I hope my explanation was understandable and the correct guess, please try out this solution!
In your main js add this.
app.run(['$rootScope', function($rootScope) {
$rootScope.test;
}]);
Here is a sample implementation of george's suggestion which is the proper way to handle this.
app.controller('LoginFormController', ['$scope','$http','$rootScope', '$state', 'stateService', function($scope, $http, $rootScope, $state, stateService) {
var userFirstName = 'John';
stateService.setFirstName('Bill');
userFirstName = stateService.getFirstName();
console.log(userFirstName); // result will be 'Bill'
}])
And the service which I usually call stateService
app.factory('stateService', [factory]);
function factory() {
var userFirstName = null;
stateService.getFirstName = function() {
return userFirstName;
};
stateService.setFirstName = function(firstName) {
userFirstName = firstName;
};
return stateService;
}
I have a basic data Service which will be used across Controllers. But I'm having an issue grabbing some data that's been added via $http.
Service:
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
_this.dropdownData.industries = resp.industries;
});
}]);
Controller:
angular.module('core').controller('SignupController', ['$scope', '$http', '$state', 'FormService', function($scope, $http, $state, FormService) {
console.log(FormService.dropdownData); // Shows full object incl industries
console.log(FormService.dropdownData.industries); // empty object {}
}]);
How do I get FormService.dropdownData.industries in my controller?
Create a service like below
appService.factory('Service', function ($http) {
return {
getIndustries: function () {
return $http.get('/json').then(function (response) {
return response.data;
});
}
}
});
Call in controller
appCtrl.controller('personalMsgCtrl', ['$scope', 'Service', function ($scope, Service) {
$scope.Industries = Service.getIndustries();
}]);
Hope this will help
Add a method to your service and use $Http.get inside that like below
_this.getindustries = function (callback) {
return $http.get('/json').success(function(resp){
_this.dropdownData.industries = resp.industries;
callback(_this.dropdownData)
});
};
In your controller need to access it like below.
angular.module('core').controller('myController', ['$scope', 'FormService', function ($scope, FormService) {
FormService.getDropdownData(function (dropdownData) {
console.log(dropdownData); // Shows full object incl industries
console.log(dropdownData.industries); // object {}
});
} ]);
Given that your console log shows the correct object, that shows your service is functioning properly. Only one small mistake you have made here. You need to access the data attributes in your return promise.
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
//note that this is resp.data.industries, NOT resp.industries
_this.dropdownData.industries = resp.data.industries;
});
}]);
Assuming that you're data is indeed existing and there are no problems with the server, there are quite a few possible solutions
Returning a promise
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
_this.dropdownData.industries = $http.get('/json');
}]);
//Controller
FormService.industries
.then(function(res){
$scope.industries = res.industries
});
Resolving with routeProvider / ui-route
See: $http request before AngularJS app initialises?
You could also write a function to initialize the service when the application starts running. At the end of the day, it is about waiting for the data to be loaded by using a promise. If you never heard about promises before, inform yourself first.
The industries object will be populated at a later point in time when the $http call returns. In the meantime you can still bind to the reference in your view because you've preserved the reference using angular.copy. When the $http call returns, the view will automatically be updated.
It is also a good idea to allow users of your service to handle the event when the $http call returns. You can do this by saving the $promise object as a property of industries:
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
_this.dropdownData.industries.$promise = $http.get('/json').then(function(resp){
// when the ansyc call returns, populate the object,
// but preserve the reference
angular.copy( resp.data.industries, _this.dropdownData.industries);
return _this.dropdownData.industries;
});
}]);
Controller
app.controller('ctrl', function($scope, FormService){
// you can bind this to the view, even though the $http call has not returned yet
// the view will update automatically since the reference was preserved
$scope.dropdownData = FormService.dropdownData;
// alternatively, you can hook into the $http call back through the $promise
FormService.dropdownData.industries.$promise.success(function(industries) {
console.log(industries);
});
});
I have a basic data Service, which will be used for multiple Controllers. In the Service, I have some predefined fields which I will get via $http.
I am currently having trouble updating that variable after getting the $http response - I keep getting the error dropdownData is not defined. I know it's probably something very basic, so please let me know.
Service:
angular.module('core').service('FormService', ['$http', function($http) {
this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
dropdownData.industries = resp.industries;
});
}]);
Try defining this in a variable:
angular.module('core').service('FormService', ['$http', function($http) {
var $this = this;
$this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
$this.dropdownData.industries = resp.industries;
});
}]);
this is redefined depending on the function call context. By storing this in a variable, you can reuse it in your closure.
Capture a reference to this and use it in the callback...
angular.module('core').service('FormService', ['$http', function($http) {
var service = this;
this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
service.dropdownData.industries = resp.industries;
});
}]);
maybe use var can solve your problem
var dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
I have abstracted my working code from a controller into a factory, but it doesn't seem to be working and I can't find what's wrong. I opted for a factory rather than a service because I wanted to execute some code that defined the variable before returning that variable; I want to get result.station (a part of the data returned by the API), not the full result.
This is my code:
var app = angular.module("myApp", []);
app.factory('api', ['$http',
function($http) {
var station_list = [];
$http({
method: 'GET',
url: 'http://api.irail.be/stations/?format=json&lang=nl'
})
.success(function(result) {
station_list = result.station;
});
return {
Stations: function() {
return station_list;
}
};
}
]);
app.controller("myController", ['api', '$scope',
function(api, $scope) {
$scope.station_list = api.Stations();
$scope.title = "Stations";
}
]);
and a working example.
Try this:
.success(function(result) {
angular.copy(result.station, station_list);
});
You had a small error, you were replacing the array instead of populating it. I used angular.copy instead of the assignment in your factory and it works
http://plnkr.co/edit/sqgKcFZAcClmkfdXHhrz
The problem is that you are dealing with asynchronous nature of AJAX.
I would suggest to have a delegate method in controller, which will be called when the service call is complete.
Something like the following:
app.controller("myController", ['api', '$scope',
function(api, $scope) {
api.Stations( function(station_list) {
$scope.station_list = station_list;
});
$scope.title = "Stations";
}
]);
The following is a service method excerpt:
return {
Stations: function(delegate) {
if (delegate)
delegate(station_list);
return station_list;
}
};
I have a problem when calling a service created using .factory in my controller.
The code looks like the following.
Factory (app.js):
.factory('Database',function($http){
return {
getDatabase: function(){
var database = {};
$http.get('http://localhost:3001/lookup').
success(function(data){
database.companyInfo = data.info.companyInfo;
});
}).
error(function(data){
console.log('Error' + data);
});
return database;
}
};
})
Controller:
angular.module('webClientApp')
.controller('MainCtrl', function (Database,Features,$scope,$http) {
$scope.databaseString = [];
$scope.quarters = ['Q1','Q2','Q3','Q4'];
$scope.years = ['2004','2005','2006','2007','2008','2009','2010',
'2011','2012','2013','2014'];
$scope.features = Features.getFeatures();
$scope.database = Database.getDatabase();
console.log($scope.database);
Now when I inspect the element in Firebug I get the console.log($scope.database) printed out before the GET statement result. $scope.database is shown as an Object {} with all the proprieties in place.
However if I try to use console.log($scope.database.companyInfo) I get an undefined as result, while instead I should get that data.info.companyInfo' that I passed from theDatabase` service (in this case an array).
What is the problem here? Can someone help me?
(If you need clarifications please let me know..)
The $http.get() call is asynchronous and makes use of promise objects. So, based on the code you provided it seems most likely that you are outputting the $scope.database before the success method is run in the service.
I build all my service methods to pass in a success or failure function. This would be the service:
.factory('Database',function($http){
return {
getDatabase: function(onSuccuess,onFailure){
var database = {};
$http.get('http://localhost:3001/lookup').
success(onSuccess).
error(onFailure);
}
};
})
This would be the controller code:
angular.module('webClientApp')
.controller('MainCtrl', function (Database,Features,$scope,$http) {
$scope.databaseString = [];
$scope.quarters = ['Q1','Q2','Q3','Q4'];
$scope.years = ['2004','2005','2006','2007','2008','2009','2010',
'2011','2012','2013','2014'];
$scope.features = Features.getFeatures();
Database.getDatabase(successFunction,failureFunction);
successFunction = function(data){
$scope.database = data.info.companyInfo;
console.log($scope.database);
});
failureFunction = function(data){
console.log('Error' + data);
}
Change your code in the following way:
.factory('Database',function($http){
return {
getDatabase: function(){
return $http.get('http://localhost:3001/lookup');
}
};
})
Then get the response in controller(Promise chain)
Database.getDatabase()
.then(function(data){
//assign value
})
.catch(function(){
})