How to run the service on page load - javascript

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
});

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

Using $timeout in service: this.func is not a function

I've been trying to use promise to end user session after certain amount of time.
Problem is, whenever a function defined in service is called from the function triggered by $timeout, the function seems to be undefined. I think it's some kind of a scope issue, but I have not managed to fix this on my own.
app.service('sessionService', function($timeout) {
var closeSession = function() {
this.resetUserInfo()
// maybe do other things as well
}
this.start = function() {
console.log("start")
promise = $timeout(closeSession, sessionLength)
}
this.resetUserInfo = function() {
// reset session
}
}
Error: this.resetUserInfo is not a function
Things I have tried
different ordering of functions
this.closeSession instead of var
$timeout(function(){closeSession(this.resetUserInfo)}, sessionLength) with proper modifications to closeSession
Note this assigned to that. So you are using the scope of the service instead of the scope of the method.
app.service('sessionService', function($timeout) {
var that = this;
var closeSession = function() {
that.resetUserInfo()
// maybe do other things as well
}
this.start = function() {
console.log("start")
promise = $timeout(closeSession, sessionLength)
}
this.resetUserInfo = function() {
// reset session
}
}
An alternative would be to make resetUserInfo a local function and then attach to it this later on. For example:
app.service('sessionService', function($timeout) {
//private definition
var resetUserInfo = function() {
}
var closeSession = function() {
resetUserInfo(); //call the private version
}
this.start = function() {
console.log("start")
promise = $timeout(closeSession, sessionLength)
}
//now expose method as public here
this.resetUserInfo = resetUserInfo;
}

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 watch object not in scope

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>

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
});

Categories

Resources