I am facing the problem with one of my custom directives.I am passing a function from view(html) as the isolated scope local property(&) but the function doesn't get triggered/called. I have already tried one of the suggestions - which is to use object literal and pass it to the function that is getting triggered but that didn't worked.
My best guess is that it's the problem with the scope it check that the following function gets returned.
function(locals) {
return parentGet(scope, locals);
};
And the scope here is referring to nested scope and the function I want to access/trigger is in parent scope.
How can I access the parent scope in this custom directive? Or is there a way to tackle this problem?
thanks
Related
I've work with some framework & even wrote some libraries for my own purpose. I now working at implementation of an AngularJs router... And looked again at DI of angular:
[...String, Function]
function.$inject
For long I've been using the first syntax. Now while testing my router, I wanted to see the behaviour if it differs for both syntaxes and how to handle this, but...
First Hand
module.controller(function SampleController()
{
});
// Since it's and `invokelater...` function which is called right away,
SampleController.$inject = [/** my component dependencies **/]
See my face when I faced:
ReferenceError: SampleController is not defined
The Other Hand
I consider it unclean to write:
function SampleController()
{
}
SampleController.$inject = [];
moddule.$inject = [];
So Finally
I know it won't work. Why? - That's my question.
Why?
We have been taught that module, class, method/functions, some for loop, if...else create new scope.
Never have I read something like:
function's parameters are evaluated in their own scope
Please Tell Me
Thanks!
Named function expressions only create a matching variable in their own scope (which is useful for calling the function recursively).
They create nothing in the scope of the function that holds them.
When you pass it as a function argument, then the variable you pass it into is scoped to the function call. i.e. function function_you_pass_the_function_to(someFunction) { } scopes the someFunction variable to itself.
When I call a function, a local scope is erected for that call. Is there any way to directly reference that scope as an object? Just like window is a reference for the global scope object.
Example:
function test(foo){
var bar=1
//Now, can I access the object containing foo, bar, arguments and anything
//else within the local scope like this:
magicIdentifier.bar
}
Alternately, does anyone have a complete list of what is in the local scope on top of custom variables?
Background: I'm trying to get down to a way of completely shifting to global scope from within a function call, the with statement is a joke, call works a little better, but it still breaks for anything declared in function scope but not in global scope, therefore I would declare these few cases in global scope, but that requires me to know what they are. The IE function execScript makes a complete shift, but that only solves the problem for IE.
Note: To anyone loading JavaScript dynamically, setTimeout(code,1) is a simple effective hack to achieve global scope, but it will not execute immediately.
No, there's no way to reference the variable object of the execution context of a function binding object of the variable environment of the execution context (that's what that thing is called [now; hence the strikethrough]; details in §10.3 of the specification). You can only access the limited view to it you get with arguments (which is very limited indeed).
Usually when I've wanted to do this, I've just put everything I wanted on an object and then used that (e.g., passed it into a function). Of course, any functions created within the context have access to everything in scope where they're created, as they "close over" the context; more: Closures are not complicated.
I know this is hugely late, and you're probably not even slightly interested any more, but I was interested in the feasibility of this too and you should be able to make a work around of some sort using:
(function(global) {
var testVar = 1;
global.scope = function(s) {
return eval(s);
}
})(this);
then running:
scope('testVar'); // 1
returns the variable from within the closure. Not particularly nice, but theoretically possible to wrap that in an object, perhaps using some validation and getters and setters if you needed?
Edit: Having re-read the question, I assume you'd want to access it without having to specify a function in the scope itself, so this probably isn't applicable. I'll leave this here anyway.
Certain versions of Netscape had a magic property in the arguments object that did what you're looking for. (I can't remember what it was called)
What about something like this?
<script type="text/javascript">
var test = {
bar : 1,
foo : function () {
alert(this.bar);
}
}
test.foo();
</script>
You don't need a keyword to reference a variable in the local scope, because it's the scope you're in.
The scenario...
I need to update data stored in the property of a scope that is the grandparent of the current scope being worked in. Of course if I attempt to simply write to the property it's not updating the grandparent scope but adding a property to the current scope.
The solution ...
To build a utility service that hosts a function to which you pass the current scope and the name of the property you are looking for. This will recursively look up the parent chain of the current scope until it finds a scope that "hasOwnProperty" of the property being looked for. It will then return a reference to that scope.
The results...
When I run the service from the console I get some strange behavior. I have some console.log
markers that trace the effectiveness of the services. Every log output is perfect and exactly what you expect, even the console.log immediately before the return statement logs, to the console, the object as you would expect, however ... the return statement returns "undefined" ... ???
Here's the service code ...
angular.module("app.services", [])
.factory('UtilitiesService', [function () {
return {
findPropertyOwner: function (scope, propertyName) {
console.log("Looking at $scope.$id = " + scope.$id);
if (!scope.hasOwnProperty(propertyName) && scope.$parent != null) {
console.log("property not found on " + scope.$id);
this.findPropertyOwner(scope.$parent, propertyName);
} else {
console.log("found on " + scope.$id);
console.log(scope);
return scope;
}
}
}
}]);
Any thoughts on why the scope is not being returned?
Thanks in advance :)
EDIT
Thanks for the answer Geoff!!
In regards to invarni's suggestion it definitely will work if I am trying to make a value available to the current scope without "hiding" the one on the grandparent. The catch is however that the grandparent scope will be the grandparent to a number of other scopes in the app. I need any updates made to the data in one descendant scope available to the other descendant scopes in different views. SO the idea is that if I change the grandparent scope it will persist and because of prototypal inheritance be available to other descendant scopes. If anybody knows a better way or sees a flaw in this concept please let me know!!
Thanks again for the feedback!
You need to return the result of your recursive function:
console.log("property not found on " + scope.$id);
return this.findPropertyOwner(scope.$parent, propertyName);
I need to update data stored in the property of a scope that is the grandparent of the current scope being worked in. Of course if I attempt to simply write to the property it's not updating the grandparent scope but adding a property to the current scope.
It seems like you might be overcomplicating this. If you have a look at how scope inheritance in Angular works you'll see that you can work around your problem by making the variable you want your grandchild-scope to be able to change a property of an object on the grandparent scope instead of having it as a property directly on the grandparent scope. That is use something like $scope.model.myProp rather than $scope.myProp and then the child scope won't create its own property.
I noticed that methods get called automatically whenever the underlying $scope variable changes.
$scope.getLength = function() {
return $scope.length;
}
My html looks like the following
<div class="test">{{getLength}}</div>
Whenever I change $scope.length, the method updates the value on the UI. I know that variables get updated because of the MVVM binding in Angular. WHy does a method get called?
It is a binding is this case too; just a binding to a function. AngularJS updates all bound elements whenever it goes through a digest cycle.
Angular does invoke those bound function everytime the scope is getting changed, no matter if this $scope.length changed or any other scope variable.
But be careful with binding too much functions into scope like this... console.log something in the function and you will see.
working on enterprise angularjs app, binding functions within big scopes can cost like 5 % of cpu power invoking bound functions containing big calculations.
When I call a function, a local scope is erected for that call. Is there any way to directly reference that scope as an object? Just like window is a reference for the global scope object.
Example:
function test(foo){
var bar=1
//Now, can I access the object containing foo, bar, arguments and anything
//else within the local scope like this:
magicIdentifier.bar
}
Alternately, does anyone have a complete list of what is in the local scope on top of custom variables?
Background: I'm trying to get down to a way of completely shifting to global scope from within a function call, the with statement is a joke, call works a little better, but it still breaks for anything declared in function scope but not in global scope, therefore I would declare these few cases in global scope, but that requires me to know what they are. The IE function execScript makes a complete shift, but that only solves the problem for IE.
Note: To anyone loading JavaScript dynamically, setTimeout(code,1) is a simple effective hack to achieve global scope, but it will not execute immediately.
No, there's no way to reference the variable object of the execution context of a function binding object of the variable environment of the execution context (that's what that thing is called [now; hence the strikethrough]; details in §10.3 of the specification). You can only access the limited view to it you get with arguments (which is very limited indeed).
Usually when I've wanted to do this, I've just put everything I wanted on an object and then used that (e.g., passed it into a function). Of course, any functions created within the context have access to everything in scope where they're created, as they "close over" the context; more: Closures are not complicated.
I know this is hugely late, and you're probably not even slightly interested any more, but I was interested in the feasibility of this too and you should be able to make a work around of some sort using:
(function(global) {
var testVar = 1;
global.scope = function(s) {
return eval(s);
}
})(this);
then running:
scope('testVar'); // 1
returns the variable from within the closure. Not particularly nice, but theoretically possible to wrap that in an object, perhaps using some validation and getters and setters if you needed?
Edit: Having re-read the question, I assume you'd want to access it without having to specify a function in the scope itself, so this probably isn't applicable. I'll leave this here anyway.
Certain versions of Netscape had a magic property in the arguments object that did what you're looking for. (I can't remember what it was called)
What about something like this?
<script type="text/javascript">
var test = {
bar : 1,
foo : function () {
alert(this.bar);
}
}
test.foo();
</script>
You don't need a keyword to reference a variable in the local scope, because it's the scope you're in.