'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
});
Related
So I'm making a service in angular but when I call it in my controller it doesn't work...
Here is the service :
app.service('AllPosts', function(){
this.posts = [
{"id":"0","username":"Simon", "age":"18"},
{"id":"1","username":"Chris", "age":"53"}
];
this.getPosts = function(){
return this.posts;
};
this.getPost = function(id){
var post={};
angular.forEach(this.posts, function(value) {
if(value.id == id){
post=value;
}
});
return post;
};
});
And in my controller I try to call it like that:
app.controller('PostsCtrl', function($scope, AllPosts){
$scope.posts = AllPosts.getPosts;
});
When I try to use the function .getPosts I have an empty white page but if I replace .getPosts by .posts I have my page loading right...
$scope.posts = AllPosts.posts;
What am I doing wrong guys, please?
In your code you are assigning $scope.posts to a function:
$scope.posts = AllPosts.getPosts;
You should call the function so that the result of the method call is assigned to $scope.posts:
$scope.posts = AllPosts.getPosts();
Now, $scope.posts will be assigned to the posts that are returned by the method.
I edited the code to work as a function or as a variable.
app.service('AllPosts', function(){
var posts = [
{"id":"0","username":"Simon", "age":"18"},
{"id":"1","username":"Chris", "age":"53"}
];
this.getPosts = function(){
return this.posts;
};
// or you can do this by calling it.
this.getPosts = this.posts;
// Using functional programming and arrow function.
this.getPost = function(id){
return this.posts.filter((value) => {
return value.id == id;
});
};
});
In your controller:
as #Amin Meyghani and # Mike C mentioned:
app.controller('PostsCtrl', function($scope, AllPosts){
// You need to comment one of these
// to use it as a function.
$scope.posts = AllPosts.getPosts();
// or if you want to use it as avarible .
$scope.posts = AllPosts.getPosts
});
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
}
}
})
I have the function inside service in angular module but how do I run the service on page load. I am not using any controller here
Code:
var app = angular.module("myTmoApppdl", [])
.service('populatePageObjsService', function () {
var self = this;
//digitalData is a global object
self.populatePage = function (digitalData) {
var dataPageObject = document.getElementById('metaJson').getAttribute("data-pageObject");
var jsonPageObject = JSON.parse(dataPageObject);
for (var key in jsonPageObject.page.pageInfo) {
var value = jsonPageObject.page.pageInfo[key];
if (digitalData.page.pageInfo.hasOwnProperty(key)) {
digitalData.page.pageInfo[key] = value;
}
}
console.log("Page data populated successfully: ", digitalData.page.pageInfo);
}();
});
I tried using the () after function but it didn't execute the function
Update:
var app = angular.module("myTmoApppdl", []).run(function () {
app.service('populatePageObjsService', function () {
var self = this;
self.populatePage = function (digitalData) {
var dataPageObject = document.getElementById('metaJson').getAttribute("data-pageObject");
var jsonPageObject = JSON.parse(dataPageObject);
for (var key in jsonPageObject.page.pageInfo) {
var value = jsonPageObject.page.pageInfo[key];
if (digitalData.page.pageInfo.hasOwnProperty(key)) {
digitalData.page.pageInfo[key] = value;
}
}
console.log("Page data populated successfully: ", digitalData.page.pageInfo);
};
});
});
You can call your service method in .run() block
var app = angular.module("myTmoApppdl", []);
app.run(function(populatePageObjsService){ // inject your service here
//use your service here
});
app.service('populatePageObjsService', function() {
// your service code here
});
With run module
Simple example
var app = angular.module("myTmoApppdl", [])
.run(function(populatePageObjsService) {
populatePageObjsService.init();
})
.service('populatePageObjsService', function() {
var self = this;
self.init = function() {
alert("run");
};
});
Plunker
Since an AngularJS service is singleton, you can be sure that your function will only be executed once, but you have to bear in mind that it is also lazily instantiated - Angular only instantiates a service when an application component depends on it - source.
With this in mind, if a service is somehow self-reliable (for example, fetching the user's country via an API call - since this can be executed only once at the start of the app and it's unlikely for the data to change), besides the usual service bindings, you can also put logic in there.
I've edited your code to showcase this approach.
angular
.module("myTmoApppdl", [])
// populatePageObjsService needs to be injected somewhere otherwise it won't get instantiated
.service('populatePageObjsService', function() {
//////////////
// Bindings //
//////////////
var self = this;
//digitalData is a global object
self.populatePage = function(digitalData) {
var dataPageObject = document.getElementById('metaJson').getAttribute("data-pageObject");
var jsonPageObject = JSON.parse(dataPageObject);
for (var key in jsonPageObject.page.pageInfo) {
var value = jsonPageObject.page.pageInfo[key];
if (digitalData.page.pageInfo.hasOwnProperty(key)) {
digitalData.page.pageInfo[key] = value;
}
}
console.log("Page data populated successfully: ", digitalData.page.pageInfo);
};
///////////////
// Run Block //
///////////////
// Calling the desired function.
self.populatePage(digitalData);
});
angular.element(document).ready(function () {
// your code here
});
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();
});
});
I have a service in which values can change from outside Angular:
angularApp.service('WebSocketService', function() {
var serviceAlarms = [];
var iteration = 0;
this.renderMessages = function(alarms, socket) {
if (! angular.equals(serviceAlarms, alarms)) {
serviceAlarms = alarms;
iteration++;
}
};
this.getAlarms = function () {
return serviceAlarms;
};
this.iteration = function () {
return iteration;
};
this.socket = initSocketIO(this);
});
The initSocketIO function makes callbacks to this services renderMessages() function and serviceAlarms variable gets changed on a steady basis.
Now i am trying to watch for changes in this service like so:
controllers.controller('overviewController', ['$scope', 'WebSocketService', function ($scope, WebSocketService) {
$scope.$watch(
function () {
return WebSocketService.iteration();
},
function(newValue, oldValue) {
$scope.alarms = WebSocketService.getAlarms();
},
true
);
}]);
to no avail. The second function provided to $watch never gets executed except on controller initialization.
I have tried with and without true as third parameter.
You should use $rootScope.$watch (not $scope.$watch)
I ended up using the solution below since $watch didn't work as excpected.
I refactored the solution to use $rootScope in combination with:
angularApp.run(['$rootScope', function($rootScope){
$rootScope.socket = {};
$rootScope.socket.alarms = [];
$rootScope.socket.faults = [];
$rootScope.socket.renderErrors = function(faults, socket) {
var faultArray = [];
angular.forEach(faults, function(error) {
error.value ? faultArray.push(error) : null;
});
if (! angular.equals($rootScope.socket.faults, faultArray)) {
$rootScope.socket.faults = faultArray;
$rootScope.apply();
}
};
$rootScope.socket.renderMessages = function(alarms, socket) {
if (! angular.equals($rootScope.socket.alarms, alarms)) {
$rootScope.socket.alarms = alarms;
$rootScope.$apply();
}
};
$rootScope.socket.socket = initSocketIO($rootScope.socket);
}]);
Now i have my socket-updated-model in all scopes to use freely in controllers and views.
Controller example:
$scope.acknowledgeAlarm = function(alarm) {
$scope.socket.socket.emit('acknowledgeAlarm', {
hash:alarm.icon.hash,
id:alarm.id
});
};
View example:
<div ng-repeat="alarm in socket.alarms">
{{alarm.name}} {{alarm.icon.progress}}
</div>