I'd like to be able to update a scope in Angular from a function outside Angular.
E.g., if I have a jQuery plugin which returns a success callback, I'd like to be able to update the scope from that success callback. Every solution I've seen for this involves calling angular.element(selector).scope and then calling $apply on the scope that is returned. However, I've also seen many comments indicating that this doesn't work when debug info is off and thus it isn't recommended, but I haven't seen any alternative solutions.
Does anyone know of a way to update the scope from outside of Angular without using angular.element(selector).scope?
Here is the accepted solution in the post:
"You need to use $scope.$apply() if you want to make any changes to a scope value from outside the control of AngularJs like a jQuery/javascript event handler.
function change() {
alert("a");
var scope = angular.element($("#outer")).scope();
scope.$apply(function(){
scope.msg = 'Superhero';
});
}
Here is a warning that .scope() doesn't work when debug data is off in the post:
"FYI according to the docs using .scope() requires the Debug Data to be enabled but using Debug Data in production is not recommended for speed reasons. The solutions below seem to revolve around scope() – rtpHarry Dec 5 '14 at 15:12 "
I don't see any alternative solution to using .scope() in this post or in other similar posts.
AngularJS access scope from outside js function
Thanks!
Update
One possible solution to not using angular.element(selector).scope was I assigned the scope in the controller I was using FirstCtrl to the window object. I injected $window into the FirstCtrl controller and did the following:
$window.FirstCtrlScope = $scope;
Then from jQuery or other javascript I could do:
var scope=window.FirstCtrlScope;
scope.$apply(function () {
// update the scope
});
Is this a good solution or are there better solutions for updating a scope without using angular.element(selector).scope?
Thanks!
I think both ways are bad. Design which sets controllers as global variables, or access to scope by html element leads to unmaintainable application with many hidden links.
If you need cooperate with jQuery plugins (or other non-angular code), wrap it into directive with clear API (attributes, bindings and callbacks).
You can assign the scope to a data attribute on the element, then access that. Take a look here where the angular-ui-bootstrap library implemented that approach.
Related
I've see the below get used but can't find any documentation on $scope. What exactly is it capturing?
$scope.find('selector')...
That is an Angular construct. The scope is the binding part between the HTML (view) and the JavaScript (controller). The scope is an object with the available properties and methods. The scope is available for both the view and the controller.
You have more detailed explanation here.
This is an Angular construct, not jQuery. $scope refers to the state of the entire Angular project; It's where all the data is stored that is bound to the templates. A change to $scope will be instantly reflected in the DOM.
Do note that Angular (at least version 1.x) relied on jQuery and has facilities in it to do jQuery-like functionality; One part was even called jQuery-lite. However, Angular uses jQuery, jQuery does not use Angular and $scope is not a jQuery concept.
Update: It has been mentioned in the comments that this could possibly just be a variable named $scope. This is totally possible since Javascript variables are allowed to start with a $. Often, people will prefix variables this way to indicate that the variables contain a jQuery object/element. However, this seems awfully coincidental.
$scope is basically part of angularjs. It shows the scope of you controller in which you are working. $scope.find('selector') will find nothing this is not the correct syntax to capture any DOM element in angularjs.
There is something that i don't understand with Angular.
I'm new to Angular, and i don't remember where but the tutorial that teached me used this syntax do apply properties to a controller's scope :
app.controller('someCtrl', function(){
this.variable = "hey!";
});
So, i was starting my web app, everything was fine, then i wanted to add some socket.io interactivity with my node.js server. So i was looking for some tutorials on how to make them work together i was confronted to this syntax :
app.controller('someCtrl', ['$scope', function($scope){
$scope.variable = "hey!";
}]);
I thought it was weird, so i looked into Angular's articles about dependency injection and scopes, i found that it was actually the way everyone is doing it... I also started to see that it allows you to interact with $rootScope and other stuff, which is i guess the way to make controllers interact with each other. But i still don't see the difference between the two. Is the first one one which is used to teach people the basics of angular in order to easily introduce them to the scope and dependency injection concepts ?
Thanks in advance for your answer.
Yes, that is confusing as hell and I wish the Angular guys would only use the second. The first one is easier to read and understand for any JS developer, however the docs used to state (AFAIK, that is gone from the docs now):
Previous versions of Angular (pre 1.0 RC) allowed you to use this interchangeably with the $scope method, but this is no longer the case. Inside of methods defined on the scope this and $scope are interchangeable (angular sets this to $scope), but not otherwise inside your controller constructor.
Since some versions, the second syntax (which injects $scope via dependency injection) is typically used, even if it is somewhat frightening to newbies, what with the array in the function variable list (which is needed for minification) and all.
The situation gets worse, though, because lately this makes a comeback in slightly different form, the "controller as" syntax:
HTML
<div ng-controller="MainController as main">
{{ main.someProp }}
</div>
Javascript
app.controller('MainController', function () {
var model = this;
model.someProp = 'Some value.'
});
So, most likely what you read is the "controller as" syntax that is currently pushing back more and more the second, dependency injection form. You can differentiate it from old examples if you look at the HTML to find XxxController as yyyy.
Typically, you don't work with this all the time in your controller's functions since the scoping of this in Javascript can easily introduce bugs. Therefore it is preferable to assign this to some local variable immediately and then work with that variable (model in my example) like you would with $scope.
TL;DR: work with the "controller as" syntax to be future-proof, but know until recently, the best practice was injecting $scope.
Basically, You should directly inject the $scope as a dependency to avoid minification problems.
When doing a minification, $scope will be translated into e and Angular will not know how to use e itself.
var app=angular.module("myApp",[]);app.controller("mainController",function(e){e.message="OH NO!"})
When directly injecting the dependency as you shown, $scope will not be renamed in any other way, so Angular will know how to handle it.
Take a look at this article on Scotch.io
I hope I've been helpful.
I have around 6 functions in my code that are not interacting with anything in the DOM, and I need those only in one specific scope.
So, is there any issue if I turn this
$scope.verifyPlaceBetAvailable = function(param) {
//something happens here
}
into this
var verifyPlaceBetAvailable = function(param) {
//something happens here
}
?
I mean, that is going to have any impact in the performance of my app?
I think if you don't populate the $scope with function that will not have affect on it or on the DOM should be better....
First of all, you should put all helpers or methods into a service, such as factory, service or provider.
About performance, I think the issue is not what you're asking. I believe can impact more about how they're written and what kind of data they're processing.
For 6 simple methods it shouldn't affect to the performance.
You should add functions in $scope only if you need them in a template otherwise use local variables or injected services if it has some business logic and does not require $scope. And it is rather improves app performance than decreases it.
You don't have to put every method in controller in scope.
As long as the method is not used in view or not interacting with anything in the DOM than you can remove that function from scope. There is no major performance issue.
For utility methods you should use factory,service or provider in angular js.
Refer AngularJS: Service vs provider vs factory
You only need to put a function in the scope if you are calling it from a view. Any other type of function could be a simple var in the controller, however many of these functions should probably be in services or factories, and not directly implemented in the controller anyway.
In my ember.js-app, Ive got one template which includes a javascript-jQuery-script. Within this script I want to call ember to read out some variables, safe them, and then change the template
Like so
finishedGame = function() {
// ember create model-entry by using "this.points"
// ember change the template to "game/credits"
};
How can I use ember to hook into an independent-running script and start functionality like switching templates etc. or ist it possible to access the controller functions from elsewhere than the ember-scripts itselv?
One very bad approach would be to use a global variable to do this and then observe it from within Ember as described in this answer, then you can trigger whatever action you require, but this is definitely not recommended.
As this other answer states, if you find yourself thinking a global variable is the best solution it's a sign that something should be refactored.
So in this case I would go with calling the finishedGame() function from within an Ember scope, like the controller (probably with Ember.$ if it is jQuery) and have this function return the values you want to save, then issue a call to a transitionToRoute method (take a look at this documentation).
My question is a lot like this: AngularJS seed: putting JavaScript into separate files (app.js, controllers.js, directives.js, filters.js, services.js) Just can I make a function in one of the files that can be called by another? And if so what do I have to add? The only reason I'm not adding to it is because it is closed. Any help would be great!
Accessing another controller would be completely wrong. You have a lot of ways to communicate between them. Here are 3 easy ones:
Scope: you can access the scope of all your parent controller using $parent or simply the $rootScope (don't overuse it or your root scope will be clutter). Remember that your scope always have your parent scope objects too until you change them. Using $watch on a scope variable can make you code cleaner when needed. (see the scope documentation)
Event: Pretty straightforward. You listen with $scope.$on and you send it with $scope.$broadcast or $scope.$emit (depending if you want the notice the children or the parents).
Service: if what you are trying to implement has no clear controller owner, you might have to consider using a service. Then, you can use it within all your controllers. (See Creating Services)
Most of the time, you will end up using the scope because you want to interact with your parent controller. Let me know if anything is unclear.