I am trying to share an id between controllers in angular
I have created a service as follows:
app.factory("idService", function() {
var id;
addId = function(id) {
id = id;
};
getId = function() {
return id;
};
});
In my controller I am trying to use this service as follows:
app.controller('photoFormController', ['$scope', '$http', 'idService' , function($scope, $http, idService) {
$scope.id = idService.getId();
}]);
I am getting an error of can't call method of undefined, obviously I am injecting the service incorrectly. Can someone help ?
EDIT:
Based on the solution below, the service no longer generates errors, however I am unable to get the id varaible back, I can see that it gets set from one controller, however it remains undefined in when retrieving :
app.factory("idService", function() {
var id;
addId = function(id) {
id = id;
console.log("added id of: " + id);
};
getId = function() {
console.log("trying to return : " + id);
return id;
};
return {
addId: addId,
getId: getId
};
});
You need to return an object inside factory. This returned object is your service instance:
app.factory("idService", function() {
var _id; //use _id instead to avoid shadowing your variable with the same name id
var addId = function(id) { //use var to avoid creating a property on the global object
_id = id;
};
var getId = function() { //use var to avoid creating a property on the global object
return _id;
};
return {
addId : addId ,
getId : getId
};
});
This is because you need to place the id within an object.
fiddle
This idea is as follows:
myApp.controller('ctrl1', function($scope, myservice) {
$scope.updateId = function() {
myservice.setId($scope.input)
};
});
myApp.controller('ctrl2', function($scope, myservice) {
$scope.data = myservice.getData();
});
myApp.service('myservice', function() {
var myservice = this;
var data = {};
myservice.setId = function(newValue) {
data.id = newValue;
};
myservice.getData = function() {
return data;
}
});
This way the data object that you get from your service sort of static, and the mutable member that you are outputting is contained within it.
You don't need to create a service in order to share some variable, just use value():
JavaScript
angular.module('app',[]).
value('share', {id: 123}).
run(['share', function(share) {
console.log(share.id); // <= 123
share.id = 345;
}]).
controller('appController', ['$scope', 'share', function($scope, share) {
$scope.id = share.id; // <= 345
}]);
Plunker: http://plnkr.co/edit/m55hmFgBvi1rwVsYMeKU?p=preview
Example of service which store data between controllers:
'use strict';
angular
.module('app')
.factory('youService', youService);
youService.$inject = ['$rootScope'];
function youService($rootScope) {
var service = {};
var questions = [];
// Data
function getData() {
return questions;
};
function setData(newQuestion) {
questions.push(newQuestion);
};
function resetData() {
questions = {};
};
// Services
service.getData = getData;
service.setData = setData;
service.resetData = resetData;
return service;
};
In controller:
angular.module('app')
.controller('yourController', yourController);
stepFourController.$inject = ['$scope', 'youService'];
function yourController($scope, youService){
// Get saved data from service
$scope.model = youService.getData();
// Set data to service
youService.setData($scope.model);
// Reset data in service
youService.resetData();
};
Best way to share data between controller is through services or factories
The service can be written as:
var myApp = angular.module('myApp', []);
myApp.service('shareId', [function () {
var shareIdService = this;
shareIdService.id = '';
shareIdService.setId = function (id) {
shareIdService.id = id;
}
shareIdService.getId = function () {
return shareIdService.id;
}
}]);
or factory may be written like as
myApp.factory('shareId', [function () {
var id = '';
return {
setId:function (id){
id=id;
},
getId:function (){
return id;
}
}
}])
Related
My code is as shown below:
angular.module('xyz.homeController', [])
.controller('homeController', ['homeService', '$scope', '$location', '$modal', '$rootScope', '$localstorage', '$window', 'GoogleSignin'
function(homeService, $scope, $location, $modal, $rootScope, $localstorage, $window, GoogleSignin) {
])
angular.module('xyz.homeService', [])
.factory('homeService', function() {
var data = {};
var deliveryOption = 0;
var payCardOption = 0;
var orderId = '';
var restaurentID = '';
var orderInfo = {};
var orderItems = [];
data.setDeliveryOption = function(info) {
this.deliveryOption = info;
};
data.getDeliveryOption = function() {
return this.deliveryOption;
};
data.setOrderId = function(orderId) {
this.orderId = orderId;
};
data.getOrderId = function() {
return this.orderId;
};
data.setRestaurentId = function(id) {
this.restaurentID = id;
};
data.getRestaurentID = function() {
return this.restaurentID;
};
data.setOrderInfo = function(info) {
this.orderInfo = info;
};
data.getOrderInfo = function() {
return this.orderInfo;
};
data.setOrderItems = function(items) {
this.orderItems = items;
};
data.getOrderItems = function() {
return this.orderItems;
};
data.setPayCardOption = function(payCardOption) {
this.payCardOption = payCardOption;
};
data.getPayCardOption = function() {
return this.payCardOption;
};
return data;
});
Now when refresh is pressed , the route is called perfectly, I have handlede the information inside the route perfectly, but somehow I am not able to restore the state of app and as a result of that, I am not able to use homeService perfectly, how to get the reference of homeService perfectly, so that I can use it?
The term you're looking for is singleton.
All services in AngularJs are singletons but you are using factory which is initialized by controller.
This will solve your problem if you're swithcing from one controller to the other.
However if you're refreshing the page, the application will reboot.
There's no way around it than using localstorage, sessionstorage, cookies...etc.
These are available through the $window service.
I'm very new to AngilarJS. I am trying to write a service in angularJS.
<script>
var module = angular.module("myapp", []);
module.service('BrandService', function ($http) {
var brands = [];
this.getBrands = function()
{
return $http.get('http://admin.localhost/cgi-bin/brand.pl')
.then(function(response)
{
brands = response.brands;
alert (brands);
});
}
//simply returns the brands list
this.list = function ()
{
return brands;
}
});
module.controller("brandsController", function($scope, BrandService) {
$scope.brandlist = BrandService.list();
alert ($scope.brandlist);
});
</script>
The statement "alert (brands);" is not getting called. What is the issue with this code. Is m missing any thing in implementation?
$http calls are always async. Meaning, even you do a .then at your service, there is no way it will properly the resolved data back into your controller. You will have to write it in your controller.
Your Service:
module.service('BrandService', function($http) {
var brands = [];
this.getBrands = function() {
//do not need the dot then.
return $http.get('http://admin.localhost/cgi-bin/brand.pl')
}
//simply returns the brands list
this.list = function() {
return brands;
}
});
In your controller:
module.controller("brandsController", function($scope, BrandService) {
BrandService.list()
.then(function(response) {
$scope.brandlist = response.brands;
alert($scope.brandlist);
});
});
In service:
this.getBrands = function() {
$http.get('http://admin.localhost/cgi-bin/brand.pl').then(function(response) {
brands = response.brands;
alert(brands);
return brands;
});
}
In controller:
$scope.brandlist = BrandService.getBrands();
alert($scope.brandlist);
There is a service I use to get data from firebase:
'use strict';
angular.module('flbi.services.trainings', [])
.factory('trainingsService', ['FBURL',
function(FBURL) {
return {
getList: function() {
var queryLimit = 10;
var firebase = new Firebase(FBURL);
firebase.child('trainings').limit(queryLimit).on('value', function(trainings) {
var allTrainings = trainings.val();
$.each(allTrainings, function(training) {
firebase.child('users/' + allTrainings[training].userid).on('value', function(user) {
allTrainings[training].user = user.val();
allTrainings[training].user.gravatar = MD5(allTrainings[training].user.email);
});
});
});
}
};
}]);
The function getList() is called from:
$routeProvider
.when('/', {
controller: 'trainingsCtrl',
templateUrl: 'views/default.html',
resolve: {
"trainings": function(trainingsService) {
return trainingsService.getList();
}
}
})
And the controller:
'use strict';
angular.module('flbi.controllers.trainings', ['flbi.services.trainings'])
.controller('trainingsCtrl', ['$scope', 'trainings',
function($scope, trainings) {
console.log(trainings); <-- just empty ....
$scope.trainings = trainings;
}]);
How can I return the data of allTrainings to my controller? I always get an empty Object. But if I check console.log(allTrainings) inner the on()-method of the service, it is full of data...
You resolve method must return a promise in order for this to work as expected. So your getList method should return a promise.
Also, prefer snapshot.forEach() to using .val() as this is highly optimized (it iterates the pointers rather than parsing and collecting all the data into an object and it also sorts the records to match the data, since JavaScript objects are inherently unordered).
angular.module('flbi.services.trainings', [])
.factory('trainingsService', ['FBURL', '$q',
function(FBURL, $q) {
return {
getList: function() {
var def = $q.defer();
var queryLimit = 10;
var firebase = new Firebase(FBURL);
firebase.child('trainings').limit(queryLimit).on('value', function(trainings) {
var promises = [];
var allTrainings = {};
trainings.forEach(function(ss) {
var key = ss.name();
var d = $q.defer();
promises.push(d.promise);
// put any other data you need in the trainings keys here
// allTrainings[key].widget = ss.child('widget').val();
firebase.child('users/' + allTrainings[key].userid).on('value', function(user) {
allTrainings[key].user = user.val();
var email = user.child('email').val();
allTrainings[key].user.gravatar = MD5(email);
d.resolve();
}, d.reject);
$q.when(promises).then(function() {
def.resolve(allTrainings);
}, def.reject);
});
}, def.reject);
return def.promise;
}
};
}
]);
I'm using the services directive in Angularjs not factory and I need to populate a json file to local variable;
/* Contains projects on the town */
leMaireServicess.service('cityService', function($http) {
// JSON regions and cities loader
this.cities = [];
// initCities
this.initCities = function() {
this.cities = $http.get('data/census/cities.js').success(function(data) {
return data;
});
return this.cities;
};
// Get city info
this.getCity = function() {
return this.cities;
};
});
And in my controller I have
// Saved game controller
leMaireControllers.controller('GameCoreCtrl', function($scope, cityService) {
/* Control the town project slides */
cityService.initCities();
$scope.city = cityService.getCity();
console.log($scope.city);
});
But instead of returning the actual data, it returns;
Object {then: function, catch: function, finally: function, success: function, error: function}
You can use a watch to make this work (see plunker)
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,cityService) {
//$scope.cities = [];
$scope.service = cityService;
cityService.initCities();
$scope.$watch('service.getCity()', function(newVal) {
$scope.cities = newVal;
console.log(newVal)
});
});
app.service('cityService', function($http) {
var that = this;
this.cities = [];
this.initCities = function() {
$http.get('data.js').success(function(data) {
that.cities = data.cities;
});
};
this.getCity = function() {
return this.cities;
};
});
$http returns a promise which is what you're setting this.cities to.
This might help explain more,
https://stackoverflow.com/a/12513509/89702
In your controller you should be able to do something like this...
cityService.initCity().then(function(data) { $scope.city = data; }
You are working with promises which represent the result of an action that is performed asynchronously. Try it this way:
leMaireServicess.service('cityService', function($http) {
this.promise = {};
// initCities
this.initCities = function() {
this.promise = $http.get('data/census/cities.js');
};
// Get city info
this.getCity = function() {
return this.promise;
};
});
And in the controller you need to put your code in a callback:
// Saved game controller
leMaireControllers.controller('GameCoreCtrl', function($scope, cityService) {
/* Control the town project slides */
cityService.initCities();
cityService.getCity().then(function(result){
$scope.city = result.data;
console.log($scope.city);
});
});
I have a factory House
'use strict';
myApp
.factory('House', [ '$http', '$location', '$rootScope', function($http, $location, $rootScope){
var numberOfDoors;
return {
loadHouse: function(){
numberOfDoors = 1;
},
numberOfDoors: numberOfDoors
};
}]);
And I have a controller Owner
myApp
.controller('OwnerCtrl', ['$rootScope', '$scope', '$location', 'House', function($rootScope, $scope, $location, House) {
$scope.buildMe = function() {
//use value from house
var sayHelloToDoors = House.numberOfDoors;
};
}]);
If I run a function House.loadHouse() in some other controller in order to set the variable numberOfDoors - I do set it, but when I switch to a page to reuse that number, I get a undefined message in Owner controller.
Why the value is cleared? It seems like another instance of House is transfered.
Could anybody help?
This is because you're assigning the value of private numberOfDoors to the field numberOfDoors in the factory.
// This following snippet ...
myApp.factory('house', function() {
var numberOfDoors;
return {
numberOfDoors: numberOfDoors
};
});
// ... will actually become
myApp.factory('house', function() {
var numberOfDoors; // === undefined
return {
numberOfDoors: undefined
};
});
Even if you would assign the private numberOfDoors an initial value, it would not behave the way you want it to.
myApp.factory('house', function() {
var numberOfDoors = 123;
return {
loadHouse: function() {
numberOfDoors = 1; // will change the private variable
// not the exposed object variable
},
numberOfDoors: numberOfDoors // will always be 123
};
});
Easiest way to make this work is doing something like this:
myApp.factory('house', function() {
return {
reset: function() {
this.numberOfDoors = 0;
},
numberOfDoors: 0
};
});
You can play with in action at this plunker.
Edit:
To encapsulate the number of doors you could do something like this:
myApp.factory('house', function() {
var _numberOfDoors = 0;
return {
reset: function() {
_numberOfDoors = 0;
},
numberOfDoors: function(value) {
if(value!==undefined) {
_numberOfDoors = value;
}
return _numberOfDoors;
}
};
});
Now from your controller you can:
var count = house.numberOfDoors(); // Get the numberOfDoors
house.numberOfDoors(++count); // Set the numberOfDoors
You'll have to change "numberOfDoors: numberOfDoors" to "numberOfDoors: function(){return numberOfDoors;}"
Please see this simple: (available in plnkr)
var service = (function(){
var privateVar = 0;
return{
updateVar: function(val){
privateVar = val;
},
getVar2: privateVar,
getVar: function(){
return privateVar;
}
}
})();
var instanceA = (function(){
service.updateVar(1);
alert(service.getVar());
})();
var instanceB = (function(){
alert(service.getVar());
alert(service.getVar2);
})();