$window on ngClick directive - angularjs

Why this doesn't work ?
Since angular expression doesn't have access to window object, i've used $window, however the below doesn't work.
<button ng-click="$window.alert('Hi There')">Hi There</button>
Angular expressions do not have access to global variables like
window, document or location. This restriction is intentional. It
prevents accidental access to the global state – a common source of
subtle bugs.

A template only has access to variables that are put on its $scope. If you need to access anything on $window from your template you'll need to inject $window into your controller and assign it to $scope there.
For example
angular.module('app').controller('Controller',
['$scope', '$window', function($scope, $window) {
$scope.$window = $window;
}]);
As pointed out in the comments, you probably don't want to expose the entire $window wrapper to your template so a better approach is to use a helper function on $scope.
ng-click="greet('Hi There')"
angular.module('app').controller('Controller',
['$scope', '$window', function($scope, $window) {
$scope.greet = function(message) {
$window.alert(message);
};
}]);

You can only call services in your controllers through scope (this is the idea of separating non-UI logic from the template)
See How to call a service function in AngularJS ng-click (or ng-change, ...)?
$window is a service, and like other services that don't relate directly to the view, they are not accessible in the templates.
angular.module('app').controller('Controller',
['$scope', '$window', function($scope, $window) {
$scope.alert=$window.alert
}]);

Related

How to make a generic close button for angular ui-views?

I need a function where I can use $window.history.back() to be called from every view regardless of what controller is controlling that page.
.run(['$rootScope', '$state', 'CommonUserModel', 'InitialiseService','$window', function($rootScope, $state, $window, commonUserModel, initialiseService) {
$rootScope.link = function(){
$window.history.back();
};
So I have this function put in the app module. Injected window object because it complained about it. But now it also complains that it "Cannot read property 'back' of undefined".
I am calling this function with $rootScope from other controllers as I read through StackOverflow. I had to inject $rootScope to other controllers like this.
homeViewModule.controller("simDetailsController", [ '$rootScope','$scope', 'ModalDialogService', 'CommonTagModel', '$location','$window',
function($scope, modalDialogService, commonTagModel, $location, $window,$rootScope) {
self.link = function(){
$rootScope.link();};
Can you give me an advice?
Keep in mind that I am pretty newbie on AngularJS I still don't get this messy, complex framework.
The order in which you have injected $window & $rootScope in the parameters list does not match the string array list.
You have mentioned '$window' as the 5th element in the string array, while, it is the 3rd element in the parameters list.
Also, in your code, '$rootScope' is the 1st element in the string array, while, it is the 6th element in the parameters list.
Replace the first lines in both of your code snippets with these:
.run(['$rootScope', '$state', 'CommonUserModel', 'InitialiseService','$window', function($rootScope, $state, commonUserModel, initialiseService, $window) {
homeViewModule.controller("simDetailsController", [ '$rootScope','$scope', 'ModalDialogService', 'CommonTagModel', '$location','$window',
function($rootScope, $scope, modalDialogService, commonTagModel, $location, $window) {
You should use routes:
https://docs.angularjs.org/api/ngRoute/service/$route

how to limit dependency injections in angularjs

I used dependency injections in my controllers as follows.
.controller('deals_list', function ($scope, global, config, services, dealService, pagination) {
Now the app was growed. Dependencies are growing too. I want limit these injections. So is there a way to limit those with global injections or something?
What kind of procedure actually should I follow?
var myApp= angular.module('myApp', []);
myApp.run(function ($rootScope, $location, $http, $timeout, YourService) {
$rootScope.MyService = YourService;
}
Used it into controller :
myApp.controller('YouCtrl', ['$scope', function ($scope) {
// scope inherits from root scope
$scope.MyService.doSomething();
}]);
What i believe you can do is to create a service that contains all the services that you want to use. The global service is like a facade into your real service.
The option then are to create on global service with all dependencies included. Or multiple facade service which group these services
app.service("Configurations",function(global,config) {
this.global=global;
this.standard=config;
});
app.service("AppServices",function(services, dealService, pagination) {
this.services=services;
// other assigments
});
Now you can inject Configurations and AppServices
This at least gives some visibility into what your controllers are dependent upon.

AngularJS : writing ui-router $state data into ancestor $state for sibling access

I have a customer management interface that I'm trying to write using ui-router. I have some states set up as
"csp"
"csp.search"
"csp.customer"
"csp.customer.details"
"csp.customer.status"
How can I use ui-router's $state data to take the csp.search result and provide it to the rest of csp and/or csp.customer? As I understand it, the data would need to be on the closest common ancestor, csp, but there's no easy/clean way to do that that I can find.
I know I can make everything a child state of csp.search, so that they would inherit $state.current.data. I could also parse $state.current.name for the first name before the ., but how universal is that? Further still, I think I could write something that climbs up the ancestry ($state.$current.parent) until finding some "top-most" signal, but I don't know what that should be.
Is there a more elegant, Angular solution?
Edit: The same question might be asked, given a known state, e.g. csp, how can I add data to it from any controller?
Your csp.search results would be on a $scope. If $scopes in additional controllers need to share the model/state/data referenced by that $scope, use a singleton object instance by registering a angular service. That one factory can be injected into as many controllers as you like, and then everything can work off that one source of truth.
Heres a simple demo of a factory sharing an Object between controllers with ui-router http://plnkr.co/edit/P2UudS?p=preview (left tab only)
Factory & Controllers:
app.factory('uiFieldState', function () {
return {uiObject: {data: null}}
});
app.controller('NavbarCtrl', ['$scope', 'uiFieldState', '$stateParams', '$state',
function($scope, uiFieldState, $stateParams, $state) {
$scope.selected = uiFieldState.uiObject;
}
]);
app.controller('LeftTabACtrl', ['$scope', 'uiFieldState', '$stateParams', '$state',
function($scope, uiFieldState, $stateParams, $state) {
$scope.selected2 = uiFieldState.uiObject;
}
]);
The factory object {uiObject: {data: null}} is injected into the controller with uiFieldState & then its simply $scope.selected = uiFieldState.uiObject; for connecting the factory to the scope ng-model="selected.data" .
This is a pretty good tutorial on angularJS services: http://ng-newsletter.com/posts/beginner2expert-services.html

angular-ui-router: what is the dependency for using $state in a controller?

This may be a really simple question but I can't find anything in the ui-router docs. I want to call the $state.go() method to change a state in a controller, but I get a "$state not defined" error.
What is the dependency I need to put on my controller in order to be able to use $state and its methods?
It is the same as with any other service - include it's name in annotated dependency list or function arguments:
//without annotation (inferred, not safe when minifying code)
function Controller($scope, $state) {...}
//inline annotation
module.controller('Controller', ['$scope','$state', function($scope, $state) {...}]);
//$inject property annotation
function Controller($scope, $state) {...}
Controller.$inject = ['$scope', '$state'];

AngularJS: how can I get $location.path to template

I need current path from url in template (content of $location.path). But not via controller, because I have a lot of controllers (and I do not want to duplicate declaration of $scope.currentUrl = $location.path;). Thanks for the advice.
AngularJS template can only see what is available in a scope so you will need somehow to put $location service in a scope. There is one scope that is always available in AngularJS application called $rootScope so it could be use for your use-case.
What you could do is to use run() method of a module to expose $location in the $rootScope:
var myApp = angular.module('myApp', []).run(function($rootScope, $location) {
$rootScope.location = $location;
});
this would make 'location' available in all templates so later on you could do in your template:
Current path: {{location.path()}}
An alternative is to use the more semantic and versatile ui-router, then in the controller, retrieve the current state, and store it on the $scope:
app.controller('MyCtrl', ['$scope', '$state', function MyCtrl($scope, $state) {
$scope.state = $state.current.name;
...
}

Resources