How to `inject` `$window` object to the `config` in AngularJS - angularjs

I am trying to inject the $window object into the config method in AngularJS, but I keep getting an error...
What is the correct way to do this?
Here is my code :
angular.module('myApp', ['$window']) //is this wrong?
.config(function ($window) { //this is not the way?
console.log($window); //console.log fails //error
})
.controller("main", function($scope) {
$scope.index = 0;
$scope.num = number[$scope.index];
$scope.increase = function () {
$scope.index += 1;
$scope.num = number[$scope.index];
}
})
Live Demo

you can't inject $window service to the config as services are not initialized at config time yet. however, you can inject them providers and get an instance. in your case:
angular.module('myApp', [])
.config(function ($windowProvider) {
var $window = $windowProvider.$get();
console.log($window);
})

Only constants and providers can be injected in config block. $window is a service. & it might not be available or configured while execution of config block so angular prevents it from using it.
You can use run block. This acts as a main method for your angular app. This is executed just right before application is instantiated. By the time run block is executed all the service will be finished configuring and are ready to be injected. So you can use $window as below,
angular.module('myApp', ['$window'])
.run(function ($window) { //use run rather than config
console.log($window);
})
.controller("main", function($scope) {
$scope.index = 0;
$scope.num = number[$scope.index];
$scope.increase = function () {
$scope.index += 1;
$scope.num = number[$scope.index];
}
})

Related

Update a $scope object from run function in AngularJS

I have my notification listener in the run function. When a notification is received I need to update a object present in $scope with a parameter present in notification object.
angular.module('app', ['ionic', 'chatsCtrl'])
.run(function($state, $ionicPlatform) {
window.FirebasePlugin.onNotificationOpen(function(notification) {
// Need to append this notification.parameter to a scope variable present in a controller
}
}
.controller('chatsCtrl', function($scope) {
// $scope.chats
});
How can I go about doing this? I don't want to use $rootScope object as $scope.chat object will get very heavy.
Thanks
you can't call scope variables/functions inside run block. since you don't want to use rootscope my suggestion is to create a service and assign values to a particular method in that service from the run block. Then get that value from the controller using the same service.
angular.module('app', ['ionic', 'chatsCtrl'])
.run(function($state, $ionicPlatform) {
window.FirebasePlugin.onNotificationOpen(function(notification) {
sampleService.setData(notification)
}
}
.controller('chatsCtrl', function($scope,sampleService) {
$scope.chats = sampleService.getData()
});
.factory('sampleService', function() {
var data;
return {
getData : function(){ return data},
setData: function(param){ data = param},
}
});

how to get variable from different AngularJS file?

How is it possible to get $scope variable from different file (with different module)? For example, I have two files - index.js and login.js, I want to get username from login.js in index.js. I tried to use services but couldn't achieve that goal. The controller doesn't see service in another angular file.
Codes partially are given below:
bookApp.controller('bookListCtrl', ['sharedProperties', function($scope, $http, sharedProperties) {
'use strict';
$scope.name = "Alice";
console.log("in book controller");
console.log("getting login name: "+sharedProperties.getProperty());
and
var authentication = angular.module('authentication', []);
authentication.service('sharedProperties', function () {
var property = 'First';
return {
getProperty: function () {
return property;
},
setProperty: function(value) {
property = value;
}
};
});
I got this exception -
angular.min.js:63 Error: Unknown provider: authentication.sharedPropertiesProvider <- authentication.sharedProperties
at Error (native)
at
There are 2 problems in the given implementation. The first problem is that the module 'authentication' needs to be a dependency for the consuming modules. The second problem is in the declaration of bookListCtrl. It needs to be defined as follows.
bookApp.controller('bookListCtrl', ['$scope','$http','sharedProperties', function($scope, $http, sharedProperties){
}]);
Can you give an example how you've used services?
Normally if you define controllers like:
app.controller('LoginController', ['UserService', function($scope) {
$scope.someMethod = function(){
// push information to service
UserService.username = $scope.username;
}
}]);
app.controller('IndexController', ['UserService', function($scope) {
// pull information from service
$scope.username = UserService.username;
}]);
It should work. I must suggest you thou to use Controller as instead of $scope. More info here: https://docs.angularjs.org/api/ng/directive/ngController

Can't inject $location inside app.config

I am trying to inject the $location and AppConstant (factory) values inside of config block.
app.config(['RestangularProvider', function (RestangularProvider) {
RestangularProvider.setBaseUrl('/san/');
RestangularProvider.setErrorInterceptor(function (response, deferred, responseHandler) {
if (response.status > 400) {
//ERROR - can't inject
angular.injector().invoke(['AppConstant', '$location', function () {
AppConstant.redirectUrl = $location.path();
$location.path('/signin');
}]);
//
return false; // error handled
}
return true; // error not handled
});
}]);
But I am not injecting directly into config, I am trying to inject in middle of config on some function scope only.
Please help me to understand the angular and javascript.
According to the docs, it says that:
The ng module must be explicitly added.
You are using it like this: angular.injector().invoke(...
But you should be using it like this: angular.injector(['ng']).invoke(...
This is typical usage:
var $injector = angular.injector(['ng']);
$injector.invoke(function($rootScope, $compile, $document) {
$compile($document)($rootScope);
$rootScope.$digest();
});
Here are the docs

How do I test a controller that watches for changes on an injected service?

I'm using a service to share data between controllers. If a value on the service changes, I want to update some data binding on my controllers. To do this, I'm using $scope.$watchCollection (because the value I'm watching is a simple array). I'm having trouble trying to figure out how to test this in Jasmine + Karma.
Here is a simple Controller + Service setup similar to what I'm doing in my app (but very simplified):
var app = angular.module('myApp', []);
// A Controller that depends on 'someService'
app.controller('MainCtrl', function($scope, someService) {
$scope.hasStuff = false;
// Watch someService.someValues for changes and do stuff.
$scope.$watchCollection(function(){
return someService.someValues;
}, function (){
if(someService.someValues.length > 0){
$scope.hasStuff = false;
} else {
$scope.hasStuff = true;
}
});
});
// A simple service potentially used in many controllers
app.factory('someService', function ($timeout, $q){
return {
someValues: []
};
});
And here is a test case that I've attempted (but does not work):
describe('Testing a controller and service', function() {
var $scope, ctrl;
var mockSomeService = {
someValues : []
};
beforeEach(function (){
module('myApp');
inject(function($rootScope, $controller) {
$scope = $rootScope.$new();
ctrl = $controller('MainCtrl', {
$scope: $scope,
someService: mockSomeService
});
});
});
it('should update hasStuff when someService.someValues is changed', function (){
expect($scope.hasStuff).toEqual(false);
// Add an item to someService.someValues
someService.someValues.push(1);
//$apply the change to trigger the $watch.
$scope.$apply();
//assert
expect($scope.hasStuff).toEqual(true);
});
});
I guess my question is twofold:
How do I properly mock the service that is used in the controller?
How do I then test that the $watchCollection function is working properly?
Here is a plunkr for the above code. http://plnkr.co/edit/C1O2iO
Your test (or your code ) is not correct .
http://plnkr.co/edit/uhSdk6hvcHI2cWKBgj1y?p=preview
mockSomeService.someValues.push(1); // instead of someService.someValues.push(1);
and
if(someService.someValues.length > 0){
$scope.hasStuff = true;
} else {
$scope.hasStuff = false;
}
or your expectation makes no sense
I strongly encourage you to lint your javascript (jslint/eslint/jshint) to spot stupid errors like the first one.Or you'll have a painfull experience in writing javascript. jslint would have detected that the variable you were using didnt exist in the scope.

Angularjs - Invoke Function from module.config

I have a code of
var viewerAngular = angular.module('ngAppDemo', ['restangular','btford.socket-io'])
.config(function(RestangularProvider) {
$.get('../config/config.xml',
function(data) {
$(data).find('contentserver').each(function() {
serverDetails.contentserver = assignServerDetails($(this));
var restprovider = RestangularProvider;
restprovider.setBaseUrl("http://"+serverDetails.contentserver.ip+":"+serverDetails.contentserver.port+"\:"+serverDetails.contentserver.port);
//$scope.init();
});
});
I need to invoke function init(), after reading the config(../config/config.xml) file.
I got an error of ReferenceError: $scope is not defined.
How can I add $scope in module.config? Or How can I call function from config?
If you need to add something to every scope in config, you can use $rootScope, but it's better practice to create a service for that data.
You can not ask for instance during configuration phase - you can ask only for providers.
var app = angular.module('app', []);
// configure stuff
app.config(function($routeProvider, $locationProvider) {
// you can inject any provider here
});
// run blocks
app.run(function($rootScope) {
// you can inject any instance here
});
See http://docs.angularjs.org/guide/module for more info.
var viewerAngular = angular.module('ngAppDemo', ['restangular','btford.socket-io'])
.config(function(RestangularProvider) {
$.get('../config/config.xml',
function(data) {
$(data).find('contentserver').each(function() {
serverDetails.contentserver = assignServerDetails($(this));
var restprovider = RestangularProvider;
restprovider.setBaseUrl("http://"+serverDetails.contentserver.ip+":"+serverDetails.contentserver.port+"\:"+serverDetails.contentserver.port);
var Scope=angular.element(document.querySelector('[ng-controller="controllerName"]')).scope();
Scope.init();
});
});

Resources