I'm trying to pass data from one controller to another using a service, however no matter what I'm trying it always returns 'undefined' on the second controller. Here is my service :
app.service('myService', ['$rootScope', '$http', function ($rootScope, $http) {
var savedData = {}
this.setData = function (data) {
savedData = data;
console.log('Data saved !', savedData);
}
this.getData = function get() {
console.log('Data used !', savedData);
return this.savedData;
}
}]);
Here is controller1 :
.controller('HomeCtrl', ['$scope','$location','$firebaseSimpleLogin','myService','$cookies','$window', function($scope,$location, $firebaseSimpleLogin, myService, $cookies, $window) {
loginObj.$login('password', {
email: username,
password: password
})
.then(function(user) {
// Success callback
console.log('Authentication successful');
myService.setData(user);
console.log('myservice:', myService.getData()); // works fine
}]);
And then controller2:
// Dashboard controller
.controller('DashboardCtrl', ['$scope','$firebaseSimpleLogin','myService',function($scope,$firebaseSimpleLogin, $location, myService) {
console.log('myservice:', myService.getData()); //returns undefined
}]);
That is simple code, unfortunately I've been struggling for a few hours now, any suggestion ? Thanks.
Created a fiddle here:
http://jsfiddle.net/frishi/8yn3nhfw/16
To isolate the problem, can you remove the dependencies from the definition for myService and see if that makes it work? Look at the console after you load the fiddle.
var app = angular.module('app', [])
.service('myService', function(){
this.getData = function(){
return "got Data";
}
})
I assume the issue is that you are returning this.savedData in the service. Try returning savedData.
this behaves different in Javascript than in other languages.
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;
}
Service:
app.service('myService', ['$scope', '$timeout', function($scope, $timeout){
return {
fn: function(messageTitle, messageContent) {
$timeout(function() {
$scope.fadeMessageSuccess = true;
}, 3000);
}
}
}]);
Controller:
app.controller("AccountCtrl", ["$scope", "Auth", "$timeout", "myService",
function($scope, Auth, $timeout, myService) {
myService.fn();
$scope.createUser = function() {
$scope.message = null;
$scope.error = null;
// Create a new user
Auth.$createUserWithEmailAndPassword($scope.accountEmailAddress, $scope.accountPassword)
.then(function(firebaseUser) {
$scope.message = "User created with uid: " + firebaseUser.uid;
console.log($scope.message);
}).catch(function(error) {
$scope.error = error;
console.log($scope.error);
});
};
}
]);
I'm trying to create a service so that I can use a function in multiple controllers but I'm have trouble getting this first one working. This is the error message I'm getting in console:
angular.js:13550Error: [$injector:unpr]
Just an observation: doesn't look like you're passing anything to the function when you're calling it. And not sure if you're wanting to add any more functionality to the service, but I think you can return the function directly and just call "myService(title, content);". But I don't think those issues would cause what you're encountering.
It looks like you were trying to return an object (a la the .factory() function) when you were trying to use .service(). Here is a dead simple explanation for .factory, .service, and .provider.
As pointed out by user2341963, injecting $scope into a service doesn't make much sense.
Also, are you sure all of your dependencies are defined and available to Angular?
Here is an example Plunkr of using a service in a controller.
Am new to angularjs. I am trying to use angular service to post data but its throwing below error
angular.js:12520 Error: [$injector:unpr] Unknown provider: frontendServiceddProvider <- frontendServicedd <- CustSignupCtrl
service.js
app.service('frontendService', function frontendService ($http, $q, $rootScope){
var list = this;
list.registerCust = function(data){
var defer = $q.defer();
$http({
url: $rootScope.endPoint,
method: "POST",
data: data
})
.success(function(res){
console.log("Successfull!");
defer.resolve(res);
})
.error(function(err, status){
console.log("Failed !");
})
return defer.promise;
}
return list;
});
customer_signup.js
app.controller('CustSignupCtrl', ['$scope', '$filter','frontendService', '$http', 'editableOptions', 'editableThemes','notify','notification','$appConstants',
function('$scope', '$filter','frontendService', '$http','editableOptions', 'editableThemes','notify','notification','$appConstants'){
$scope.pw1 = '';
$scope.registerCustomer = function (data) {
return frontendService.registerCust(data)
}
$scope.signupcustomer = function(){
var payload= {
first_name: $scope.custForm.fname,
last_name: $scope.custForm.lname,
phone: $scope.custForm.phone,
email:$scope.custForm.email,
username:$scope.custForm.username,
password:$scope.custForm.pw1,
usertype:3
}
console.log("inside function");
$scope.registerCustomer(payload).then(function(data){
notification.success(data.result);
},function(err){
notification.error("Error: contact system admin");
});
}
}
])
I have given reference of both js files in index.html.. not getting where am doing wrong.. can anyone help
app.controller('CustSignupCtrl', ['$scope', '$filter', 'frontendService', '$http', 'editableOptions', 'editableThemes','notify','notification','$appConstants',
function($scope, $filter, frontendService, $http, editableOptions, editableThemes, notify, notification, $appConstants){
$scope.pw1 = '';
});
Whatever you inject into controller, should be in the same order.
Remove quotes accross the injectables inside function.
This can be a dependency injection mismatch sort of problem
AngularJS injects object into the function as it sees them inside []
For example if you declare a function inside your js file, say like this
var app = angular.module('app',[]);
app.controller('maincntrl',function($scope){
});
var search = function($scope,searchtext,searchfilters,searchareas)
{
return 'result'
}
console.log(angular.injector.annotate(search));
The result you shall get in your console will be
["$scope","searchtext","searchfilters","searchareas"]
AngularJS parses the function parameters as an array
It goes through each array elements and the moment it sees "$scope", it injects scope object into that position
Now the syntax which you have used is basically used for minification
So according to your declaration
app.controller('CustSignupCtrl', ['$scope','frontendService', '$filter','frontendService', '$http', 'editableOptions', 'editableThemes','notify','notification','$appConstants',
function('$scope', '$filter','frontendService', '$http','editableOptions', 'editableThemes','notify','notification','$appConstants'){
});
So
$scope--> shall be injected into $scope
frontendService-->shall be injected into $filter
$filter--> shall be injected into frontendService
.
.
.
so on
Also the errors(which you mentioned in comments) are occurring because you have declared function parameters as strings in which case the dependency injection is not happening. Fixing these things shall solve your problem
I'm new in angularJS and I got a small problem which is :
(i'll explain some details)
I have a SQL database which is deployed in Azure and I get the data from web services.
when I want to retrieve data from the database and expose it in the view , it works.
this is the controller :
var app = angular.module('ngdemoApp.controllers', []);
app.controller('CustomerViewCtrl', ['$scope', '$routeParams', 'ShowCustomerFactory','LikeProfilCustomerFactory','ShowManagerFactory',
function ($scope, $routeParams, ShowCustomerFactory,LikeProfilCustomerFactory,ShowManagerFactory) {
$scope.incrementLikeProfil = function (id) { LikeProfilCustomerFactory.likeProfil({id:$scope.customer.Id});
$scope.customer = ShowCustomerFactory.show({id: $routeParams.id});
}
$scope.customer = ShowCustomerFactory.show({id: $routeParams.id});
}]);
notice that the customer is in the database so it has properties in other word if I do {{customer.Id}} this expression shows me the value in the view.
However, when I want to use the $scope.customer in the controller like this
app.controller('CustomerViewCtrl', ['$scope', '$routeParams', 'ShowCustomerFactory','LikeProfilCustomerFactory','ShowManagerFactory',
function ($scope, $routeParams, ShowCustomerFactory,LikeProfilCustomerFactory,ShowManagerFactory) {
$scope.incrementLikeProfil = function (id) {
LikeProfilCustomerFactory.likeProfil({id:$scope.customer.Id});
$scope.customer = ShowCustomerFactory.show({id: $routeParams.id});
}
$scope.customer = ShowCustomerFactory.show({id: $routeParams.id});
$scope.test = $scope.customer.Id;
}]);
the $scope.test cannot be filled by $scope.customer.Id, at the same time the $scope.customer is filled and the view can display the value of customer but when I want to display the $scope.test in the view, i didn't get any responce.
Is there any solution ? Thank you
$scope.customer = ShowCustomerFactory.show({id: $routeParams.id});
If the above statement is making a service request and fetching data from server. This will be async and won't be available.
But in the next statement itself, you are setting
$scope.test = $scope.customer.Id;
At this point of time, $scope.customer may be undefined. That's why you're not getting the value.
You must put this statement in the then() function of promise $scope.test = $scope.customer.Id;
So in your service, return promise using $http or $q. And in your controller:
ShowCustomerFactory.show({id: $routeParams.id}).then(function(data) {
$scope.customer = data;
$scope.test = $scope.customer.id;
});
Another workaround would be :
Initially set
$scope.customer = {};
Also here is my service I use $resource :
services.factory('ShowCustomerFactory', function ($resource) {
return $resource(url + '/customerService/getCustomer?id=:id', {}, {
show: { method: 'GET',params: {id: '#id'} }
});
});
I'm not able to get the data binding between controller and service working.
I have a controller and a factory which makes an HTTP call. I would like to be able to call the factory method from other services and see the controller attributes get updated. I tried different options but none of them seem to be working. Any ideas would be greatly appreciated.
Please see the code here:
http://plnkr.co/edit/d3c16z?p=preview
Here is the javascript code.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
app.controller('EventDetailCtrl', ['$http', 'EventDetailSvc', '$scope',
function ($http, EventDetailSvc, $scope) {
this.event = EventDetailSvc.event;
EventDetailSvc.getEvent();
console.log(self.event);
$scope.$watch(angular.bind(this, function () {
console.log('under watch');
console.log(this.event);
return this.event;
}), function (newVal, oldVal) {
console.log('under watch2');
console.log(newVal);
this.event = newVal;
});
}])
.factory('EventDetailSvc', ['$http', function ($http) {
var event = {};
var factory = {};
factory.getEvent = function() {
$http.get('http://ip.jsontest.com')
.then(function (response) {
this.event = response.data;
console.log('http successful');
console.log(this.event);
return this.event;
}, function (errResponse) {
console.error("error while retrieving event");
})
};
factory.event = event;
return factory;
}]);
It seems to me that you have nested the event object inside of a factory object. You should be returning event directly instead wrapping it with factory. As it stands now you would need to call EventDetailSvc.factory.event to access your object.