how to get a service from angularjs app - javascript

I have a variable that contains my angular app
(was instantiated with:)
var app = angular.module('app', [...]);
And I want to get the $timeout service.
How can I get this service from the it?
I want something like:
var timeout = app.getService('$timeout');
or
app.something('$imeout', function($timeout) {
...
} // like controller() does
Where I want to use it:
define([], function () { // I can import my angular module 'app', or 'angular'
return {
'some_function': function () {
$timeout(function() { ... do something ... }, 1000);
}
}
}
This is a service (with requirejs), and my controllers will require it.

What you should do is:
app.controller("myCtrl",["$timeout", "otherService" ,function($timeout, otherService){
$timeout(function() {
otherService.updateService('Hi');
}, 3000);
}]);

Related

How to call a function from another module

In my angularJS application, I have two modules : module A and module B.
angular.module('A').controller('ACtrl',function($scope){
$scope.alertA = function(){alert('a');}
//...
});
angular.module('B').controller('BCtrl',function($scope){
//...
});
How to call the function alertA in the module B ?
You need to define a factory in module A:
var moduleA= angular.module('A',[]);
moduleA.factory('factoryA', function() {
return {
alertA: function() {
alert('a');
}
};
});
Then use the alertA factory in module B:
angular.module('B',['A']).controller('BCtrl',function($scope,'factoryA'){
factoryA.alertA();
});
Refactor your code in following these steps:
Define a service in module A
Add module A as dependency to module B
Inject the service into the controller
Here is an example:
angular.module('A').service('API', function ($http) {
this.getData = function () { return $http.get('/data'); };
});
angular.module('B', ['A']).controller('dashboardCtrl', function ($scope, API) {
API.getData().then(function (data) { $scope.data = data; });
});

AngularJS factory unit testing with dependencies

I am trying to test some AngularJS factories with Jasmine. It works fine for factories that don't have any dependencies. One of my factories uses Angular Material's $mdToast as dependency.
The factory:
(function() {
'use strict';
angular
.module('myModule')
.factory('ToastFactory', ToastFactory);
ToastFactory.$inject = ['$mdToast'];
function ToastFactory($mdToast) {
var service = {
showToast1: showToast1,
showToast2: showToast2
};
return service
function showToast1() {
return $mdToast.show($mdToast.build({
templateUrl: 'path'
}));
}
function showToast2() {
return $mdToast.show($mdToast.build({
templateUrl: 'path'
}));
}
}
})();
And here is one of the working tests for another factory without dependencies.
describe('myFactory', function() {
//Injector Service
var $injector;
//Set Module
beforeEach(function() {
angular.module('myModule');
});
//Inject injector service
beforeEach(inject(function() {
$injector = angular.injector(['myModule']);
}));
describe('SampleTest', function() {
it('should be true', function() {
//Arrange
var factory = $injector.get('myFactory');
//Act
var res = factory.testMethod();
//Assert
expect(res).toBe(true);
});
});
})
I know how to do it for controllers, but not for factories.

Not able to use cache properly in Angular JS

I have the following code snippet in my angular js web application. Intention is to use cache in controller to make the app faster.
I have defined the following cache factory in my services.js file which is to be utilized by several controllers in my app:
appServices.factory('AppCache', ['$cacheFactory', function($cacheFactory){
return $cacheFactory('app-cache');
}]);
Now I have the following code in one of my controllers:
appControllers.controller('pageController', ['$scope', 'AppCache', 'AnotherService',
function pageController($scope, AppCache, AnotherService) {
$scope.init = function () {
if (angular.isUndefined(AppCache.get('d')))
{
AnotherService.get({},
function success(successResponse) {
$scope.data = successResponse.response.r;
AppCache.put('d', $scope.data);
},
function error(errorResponse) {
console.log("Error:" + JSON.stringify(errorResponse));
}
);
}
else
$scope.data = AppCache.get('d');
}
}
The problem is I am not able to save or retrieve any data in / from the cache. My page becomes blank when I use the above code as no data is retrieved.
Please help me understand my mistake.
You named your cache 'app-cache', and you try to access it by 'd'. In the controller, just replace the 'd' with 'app-cache', it should work:
appControllers.controller('pageController', ['$scope', 'AppCache', 'AnotherService',
function pageController($scope, AppCache, AnotherService) {
$scope.init = function () {
if (angular.isUndefined(AppCache.get('app-cache')))
{
AnotherService.get({},
function success(successResponse) {
$scope.data = successResponse.response.r;
AppCache.put('app-cache', $scope.data);
},
function error(errorResponse) {
console.log("Error:" + JSON.stringify(errorResponse));
}
);
}
else
$scope.data = AppCache.get('app-cache');
}

Mocking custom provider injected into provider when unit testing Angular in Jasmine

I'm unit testing a provider in Jasmine, which relies on another provider. There's no configuration associated with this provider. When mocking a provider, I've read you're supposed to use something like
beforeEach(module(function ($provide) {
mockInjectedProvider = { };
$provide.value('injected', mockInjectedProvider );
}));
which works fine for me when injecting a custom provider into a service. When injecting them into a provider it doesn't work though. The code doesn't fail, but what gets executed when testing is the actual provider, not the mocked one. Abstracted example below.
var mockInjectedProvider;
beforeEach(function () {
module('myModule');
});
beforeEach(module(function ($provide) {
mockInjectedProvider = {
myFunc: function() {
return "testvalue"
}
}
};
$provide.value('injected', mockInjectedProvider );
}));
beforeEach(inject(function (_base_) {
baseProvider = _base_;
}));
it("injectedProvider should be mocked", function () {
var resultFromMockedProvider = baseProvider.executeMyFuncFromInjected();
expect(resultFromMockedProvider).toEqual("testvalue");
}); // Here instead of using my mock it executes the actual dependency
In the $provide.value statement I've tried including both injected and injectedProvider, as well as using $provide.provider and mocking a $get function on it but nothing seems to work. I just can't get it to mock away the actual provider. Abstracted base provider looks like this.
(function (ng, module) {
module.provider("base",
["injectedProvider", function (injectedProvider) {
this.executeMyFuncFromInjected= function() {
return injectedProvider.myFunc(); // let's say this returns "realvalue"
}
this.$get = function () {
return this;
};
}]
);
})(window.angular, window.angular.module("myModule"));
Everything in my code is working except the Jasmine mocking.
In this case is better to just mock the return value instead of the provider.
var mockInjectedProvider;
beforeEach(function () {
module('myModule');
});
beforeEach(inject(function (_injected_) {
spyOn(_injected_, "myFunc").and.returnValue("testvalue");
}));
beforeEach(inject(function (_base_) {
baseProvider = _base_;
}));
it("injectedProvider should be mocked", function () {
var resultFromMockedProvider = baseProvider.executeMyFuncFromInjected();
expect(resultFromMockedProvider).toEqual("testvalue");
}); // Here instead of using my mock it executes the actual dependency

run function of a scope in other scope angularjs

How can I run the working code in createAdmobBanner function in another controller?
angular.module('starter', ['ionic', 'starter.controllers'])
.run(function ($ionicPlatform) {
$ionicPlatform.ready(function () {
var admobid = {};
if (/(android)/i.test(navigator.userAgent)) {
admobid = {
banner: 'ca-app-pub-3815248714018431/123456789'
};
}
function createAdmobBanner() {
AdMob.createBanner({
adId: admobid.banner
adSize: 'SMART_BANNER',
position: 8
});
}
createAdmobBanner();
});
})
I got createAdmobBanner is not defined if I simply do createAdmobBanner() in my controllers. I tried $rootScope but the plugin doesn't seem work with that.
You need to add it into a service or attached in on $rootScope,
$rootScope solution - faster to implement but "dirty"
.run(function($ionicPlatform,$rootScope) { //add $rootScope dependency injection
$rootScope.createAdmobBanner = function(){
AdMob.createBanner( { adId:admobid.banner
adSize: 'SMART_BANNER',
position:8
});
}
$rootScope.createAdmobBanner()
into your controllers, add the dependency $rootScope and call your function $rootScope.createAdmobBanner
Service Solution - cleaner & reusable
Create a new service that has your function
Inject your service into run
call your service function into run
inject your service into controllers
call your service function into controllers
I just found this link here. Give it a try. The important code looks like this:
var admobApp = angular.module('myapp', ['ionic'])
.run(function($ionicPlatform, $ionicPopup) {
$ionicPlatform.ready(function() {
if(window.plugins && window.plugins.AdMob) {
var admob_key = device.platform == "Android" ? "ANDROID_PUBLISHER_KEY" : "IOS_PUBLISHER_KEY";
var admob = window.plugins.AdMob;
admob.createBannerView(
{
'publisherId': admob_key,
'adSize': admob.AD_SIZE.BANNER,
'bannerAtTop': false
},
function() {
admob.requestAd(
{ 'isTesting': false },
function() {
admob.showAd(true);
},
function() { console.log('failed to request ad'); }
);
},
function() { console.log('failed to create banner view'); }
);
}
});
});
The admob stuff is within $ionicPlatform.ready(function() { and is defined like this var admob = window.plugins.AdMob;
Does that help?
Try to define external angular service/factory and provide this service to any controller you need using dependency injection.
This is a good practice to share common logic or data in this way.
EDIT:
angular.module('starter', ['ionic', 'starter.controllers']);
angular.module('starter').factory('bannerFactory',function(){
return {
createAdmobBanner: function(){
window.plugins.AdMob.createBanner({ adId:admobid.banner
adSize: 'SMART_BANNER',
position:8
});
}
}
});
angular.module('starter').controller('anyController',['bannerFactory', function(bannerFactory){
bannerFactory.createAdmobBanner();
}]);
angular.module('starter').run(function ($ionicPlatform,bannerFactory) {
$ionicPlatform.ready(function () {
bannerFactory.createAdmobBanner();
});
});

Categories