angularjs undefined object in service - javascript

I want to share data from controller 1 to another controller
I get an undefined error in my 2nd controller. Is anyone able to tell me whats wrong with my code?
Service
app.service('var_transfer_service', function(){
var test_var;
return {
getVar: function () {
return test_var;
},
setVar: function( _test_var ) {
test_var = _test_var;
console.log(test_var);//show the object content in my console
}
}
})
Controller 1
app.controller('homeCtrl', function($scope,$http, $filter ,var_transfer_service){
$scope.search_item = function ($event,item){
console.log(item)
var latt = item.lat;
var lngt = item.lng;
var_transfer_service.setVar(item);
}
});
Controller 2
app.controller('MapCtrl',function($scope,var_transfer_service, $state, $cordovaGeolocation) {
var transferred_var = var_transfer_service.getVar();
console.log(transferred_var); //undefined object
});

It's undefined because it's not initialized:
var test_var;
You only set a value on the setVar function which gets called in the $scope.search_item function in the secound controller (that you never call).
What is your indented behaviour?

You used a service, but wrote a factory.
Angular services return the function instance, so put functions on the function scope, using "this".
Using service:
app.service('var_transfer_service', function(){
var test_var;
this.getVar = function () {
return test_var;
};
this.setVar = function( _test_var ) {
test_var = _test_var;
console.log(test_var);//show the object content in my console
}
}
Basically, angular service returns the function itself, but factory return the return value of the function - so, you wrote a factory.
So your code would work, if you will use app.factory:
app.factory('var_transfer_service', function(){
var test_var;
return {
getVar: function () {
return test_var;
},
setVar: function( _test_var ) {
test_var = _test_var;
console.log(test_var);//show the object content in my console
}
}
})

Related

bcbankApp.accsummary module AccountSummaryController should have a getAccountSummary function FAILED in angular js

I am working on Banking app using Angularjs on hackerrank where I am stuck at point.I am trying to call my function from Account summary controller but It is saying that No such function exist in my controller
Here is my code
AccountSummarycontroller.js
// Create the controller AccountSummaryController with getAccountSummary function that access accountSummaryService which is already defined in account-summary.service.js. Use $state for Transition from one page to another.
(function() {
'use strict';
var appContr = angular.module('abcbankApp.accountSummary', ['abcbankApp.accountSummaryService']);
appContr.controller('AccountSummaryController', function(AccountSummaryService) {
var ActSumCtrl = this;
// this.AccountSummaryService.getAccountSummary();
ActSumCtrl.accountList = [];
ActSumCtrl.accountList = AccountSummaryService.getAccountSummary();
});
})();
AccountSumaaryService.js
// Create the service AccountSummaryService with getAccountSummary function which should return the account details from data/account-summary.json using $http.get.
(function() {
'use strict';
var appServc = angular.module('abcbankApp.accountSummaryService', []);
appServc.factory('AccountSummaryService', ['$http',
function($http) {
return {
getAccountSummary: function() {
var data;
$http.get('./data/account-summary.json')
.then(function(response) {
data = response.data;
});
return data;
}
};
}]);
})();
But I am getting error something like below
abcbankApp.accsummary module AccountSummaryController should have a getAccountSummary function FAILED.Expected false to be true.
Testfile.js
describe('AccountSummaryController', function() {
it('Controller definition', function() {
expect(AccountSummaryController).toBeDefined();
});
it('should have a getAccountSummary function', function() {
expect(angular.isFunction(AccountSummaryController.getAccountSummary)).toBe(true);
});
});
});
})();
Any Help will be Appreciated.Thanks in advance
Well to answer your question lets begin with your test case as it is showing that AccountSummaryController.getAccountSummary should be defined
So you should call your function with your controller name and function name
Here is modified code
(function() {
'use strict';
var appContr = angular.module('abcbankApp.accountSummary', ['abcbankApp.accountSummaryService']);
appContr.controller('AccountSummaryController', function(AccountSummaryService) {
var ActSumCtrl = this;
// this.AccountSummaryService.getAccountSummary();
ActSumCtrl.accountList = [];
ActSumCtrl.getAccountSummary=function()
{
//move your logic here
}
ActSumCtrl.accountList = AccountSummaryService.getAccountSummary();
});
})();
Let me know in comment weather it worked or not

How can i pass variable values from one controller to another? [duplicate]

This question already has answers here:
AngularJS: How can I pass variables between controllers?
(16 answers)
Closed 7 years ago.
I have two different controller where i am trying to pass variable values to do some actions, I used $broadcast angularJS event but its not working. Is there any other solution to achieve this task ?
I understand there is already question asked regarding variables between controller but i wanted to know what are other possible soultions.
ctrl1.js
$scope.viewAssessmentFrmCycle = function(assessmentId) {
$scope.$broadcast('viewAssessment',assessmentId);
}
ctrl2.js
$scope.$on('viewAssessment',function(s,assessmentId){
console.log(assessmentId);
$location.path('/rcsa/editAssessmentFromCycle/'+assessmentId+);
});
Use a service.
angular.module('myApp', [])
.service('ShareThis', function () {
var value = 'myValue';
return {
getValue: function () {
return value;
},
setValue: function(newValue) {
value = newValue;
}
};
});
Then you can access this in each controller by either setting or getting...
Eg:
myApp.controller('Ctrl1', function($scope, ShareThis) {
$scope.value = ShareThis.getValue();
});
myApp.controller('Ctrl2', function ($scope, ShareThis) {
$scope.setVal = function(val) {
ShareThis.setValue(val);
}
}
You can create a factory to hold the data.
Factory:
angular.module('myModule').factory('commonData', function(){
var commonValue = {};
return {
getData : function(){ return commonValue },
setData : function(newData) { commonValue = newData }
}
});
Then inject this factory into your controller and use the set and get functions to manipulate the data.
Use factory to hold your data..
var app = angular.module('test', []);
// create a mediator factory which will persist the data
app.factory("MediatorFactory", function() {
return {
obj: {
value: ""
}
};
});
app.controller("FirstCtrl", ["MediatorFactory", function(mediator) {
this.variable1 = mediator.obj;
}]);
app.controller("SecondCtrl", ["MediatorFactory", function(mediator) {
this.variable2 = mediator.obj; // this.variable2 = this.variable1 in the controller1
}]);

AngularJS sharing async data between controllers

There's quite a few topics out there covering issues with sharing data between controllers, but I havn't found any good answers for my case.
I have one controller that fetches data asynchronous using promise. The controller then makes a copy of the data to work with within that scope. I then have a second controller which I want also want to work on the same copy of data that of the first controller so they both share it.
Here's some code simplified to serve as example:
.controller('firstController', function ($scope, someService){
var vm = this;
someService.getData().then(function(data) {
angular.copy(data, vm.data); //creates a copy and places it on scope
someService.setCurrentData(vm.data)
}
});
.controller('secondController', function ($scope, someService){
var vm = this;
vm.data = someService.getCurrentData(); //Triggers before the setter in firstController
});
.factory('someService', function(fetchService){
var _currentData = {};
var getData = function(){
return fetchService.fetchData().then(function(data) { return data; });
};
var getCurrentData = function(){
return _currentData;
}
var setCurrentData = function(data){
_currentData = data;
}
});
As the getData is async will the setCurrentData be triggered after the getCurrentData, so getCurrentData gives a different object and does not change to the correct one. I know you can solve this with broadcast and watch, but I'm trying to avoid using it if possible.
Refactor your factory to check if the _currentData variable has already been set - then you can simply use callbacks:
app.factory('someService', function(fetchService){
var _currentData = null;
var setCurrentData = function(data){
_currentData = data;
}
var getData = function(callback) {
if (_currentData == null) {
fetchService.fetchData().success(function(data) {
setCurrentData(data);
callback(data);
});
} else {
callback(_currentData);
}
};
/*
var getCurrentData = function(){
return _currentData;
}
*/
});
Now, calling your getData service will check if the data is already got and stored, if so, use that, else go get it!
someService.getData(function(data) {
console.log(data); //yay for persistence!
})
I would solve in this way:
.controller('firstController', function ($scope, $rootScope, someService){
var vm = this;
someService.getData().then(function(data) {
angular.copy(data, vm.data); //creates a copy and places it on scope
someService.setCurrentData(vm.data);
$rootScope.$broadcast('myData:updated');
}
});
.controller('secondController', function ($scope, $rootScope, someService){
var vm = this;
$rootScope.$on('myData:updated', function(event, data) {
vm.data = someService.getCurrentData();
});
});

Angular js , passing object from service

'use strict';
var app = angular.module('app');
app.factory('currTripService', function() {
var currtrip ='';
return{
setCurrTrip: function(trip){
currtrip = trip ;
},
getCurrTrip: function(){
return currtrip ;
},
}
});
app.controller('TripCreateController', function($scope, $location, Trip,currTripService) {
//The save method which is called when the user wants to submit their data
$scope.save = function() {
//Create the forum object to send to the back-end
var trip = new Trip($scope.trip);
console.log(trip);
currTripService.setCurrTrip(trip);
console.log(currTripService.getCurrTrip());
//Save the forum object
trip.$save(function() {
//Redirect us back to the main page
$location.path('/trip/day/1');
}, function(response) {
//Post response objects to the view
$scope.errors = response.data.errors;
});
}
});
app.controller('TripDayCreateController',function($scope,$routeParams,currTripService){
$scope.items=[];
$scope.trip = currTripService.getCurrTrip();
console.log($scope.trip.city);
// $scope.products = productService.getProducts();
$scope.addItem = function(item) {
$scope.items.push(item);
$scope.item = {};
}
});
When i click on /trip/new , its does the save in TripCreateController and set the trip object inside currTripService.
Then when redirected to TripDayCreateContoller the console.log(currTripService.getTrip()) , returns 'undefined'
Is it because Trip is an object ? How can i fix this ?
try this:
app.factory('currTripService', function() {
var currtrip = '';
var self = this;
return{
setCurrTrip: function(trip){
self.currtrip = trip ;
},
getCurrTrip: function(){
return self.currtrip ;
},
}
});
When you declare a function, this scope changes so currtrip was only existing in your getter/setter functions, but not outside.
The best way to do this is to use a class. Below is a an example of a class from CoffeeScript.
class currTripService
# storage object
#data = null
# get data
get: =>
return #data
# set data
put: (data) =>
#data = data
app.factory('currTripService', currTripService)
However if you want to do this without a class method then you can instead use something that would imitate a class:
var currTripService = function () {
// storage variable
var currTrip = null
// reference to this element
var _this = this
return{
// set this trip value
setCurrTrip: function(trip){
_this.currtrip = trip;
},
// get this trip value
getCurrTrip: function(){
return _this.currtrip;
},
}
}
app.factory('currTripService', currTripService);
Just a note: I put the function outside the factory to imitate how you'd typically call a class, but you can obviously just put all of the code in the function declaration.
app.factory('currTripService', function () {
// logic
});

Angular service not passing between controllers

I have two controllers on a parallel scope level I need to pass data between:
function TableRowCtrl($scope, $http, sharedProperties) {
console.log(sharedProperties.getProperty());
$scope.items = sharedProperties.getProperty();
}
and
function SideNavCtrl($scope, $http, sharedProperties) {
$scope.customers = undefined;
var temp = "cats";
$http.get('data/customers.json').success(function(data) {
$scope.customers = data;
temp = "dogs";
sharedProperties.setProperty(temp)
});
sharedProperties.setProperty(temp);
console.log(sharedProperties.getProperty());
}
I am trying to use a service to do this (via examples I have seen) :
angular.module('myApp', []).service('sharedProperties', function() {
var property = "Cats";
return {
getProperty: function() {
return property;
},
setProperty: function(value) {
property = value;
}
};
});
However - when I try and set the data in the SideNavCtrl http success function, it does not bubble out - the service still returns 'cats' as its value. From what I have read, services are supposed to be global, and setting data in them should be permanent (as is its purpose). What am I doing wrong, and how can I get data between these two controllers on the same scope?
The problem is your TableRowCtrl saves the result of a function in its scope variable. When the service itself changes, the value in the scope does not because at that point, it's a simple property. You can either expose your service directly in the scope or wrap $scope.items in a function instead:
function TableRowCtrl($scope, $http, sharedProperties) {
$scope.items = function() { return sharedProperties.getProperty(); };
}
// And in your view
{{ items() }}
Or
function TableRowCtrl($scope, $http, sharedProperties) {
$scope.shared = sharedProperties;
}
// And in your view
{{ shared.getProperties() }}
Edit: Simple plunkr here
Edit #2:
If the problem is a binding that isn't updated because of an asynchronous process, you can use $scope.$apply:
$http.get('data/customers.json').success(function(data) {
$scope.customers = data;
temp = "dogs";
sharedProperties.setProperty(temp)
if(!$scope.$$phase)
$scope.$apply();
});
Edit 3:
I've recreated your $http.get and updated the plunkr and it works. Based on what you are showing in your questions, it should work using function instead of regular properties.
#SimomBelanger already identified the problem. I suggest using objects rather than primitives, then you don't need to call functions in your view:
<div ng-controller="TableRowCtrl">items={{items.property}}</div>
<div ng-controller="SideNavCtrl">customers={{customers}}</div>
app.service('sharedProperties', function () {
var obj = {
property: "Cats"
};
return {
getObj: function () {
return obj;
},
setObjProperty: function (value) {
obj.property = value;
}
};
});
function SideNavCtrl($scope, $timeout, sharedProperties) {
$scope.customers = undefined;
var temp = "cats";
$timeout(function () {
$scope.customers = 'some data';
temp = "dogs";
sharedProperties.setObjProperty(temp);
}, 2000);
sharedProperties.setObjProperty(temp);
}
function TableRowCtrl($scope, $http, sharedProperties) {
$scope.items = sharedProperties.getObj();
}
fiddle
In the fiddle I use $timeout to simulate an $http response.
Because getObj() returns a (reference to an) object, updates to that object are automatically picked up by the view.

Categories

Resources