In AngularJS is $scope actually the parent object's body? If so, does this mean that the controller in the image below (called "MainCtrl") is essentially setting two variables within the MODULE and that "categories" and "bookmarks" would now be available within the module called "Eggly?"
OR...
Is the function, passed in as the 2nd argument of the controller function actually NEWING UP a new empty object and passing that new object in as the $scope? That would indicate that the two variables are being set on the new object and the new object, with the new variables, would be set as the controller.
From a C# perspective
In C# it is common to pass in "this" when creating an instance of an object within an object IF the child needs to access the parent. The child would receive this and have access to any PUBLIC properties or methods. It appears that passing in $scope does something similar except that EVERYTHING in the parent is available from the child (probably a function).
Setting a property on $scope exposes the property to whoever sees this scope, typically child directives and controllers.
It doesn't set it "on the module" - whatever that means.
Related
Let's say my grandparent component/directive's scope variable is declared like this: $scope.g = { // methods here };
In each of my nested component's/directive's controllers, I'm referring to that variable like $scope.$parent.$parent.g and then calling some function off of g such as $scope.fromNgClick = function() { $scope.$parent.$parent.g.run(); };. That works great (though I would like a better way of referring to ancestors such as an alias name? instead of a $parent chain).
When I natively drag a component from it's grandparent component into another grandparent sibling component (got that?), the same $scope.fromNgClick = function() { $scope.$parent.$parent.g.run(); }; still points to the original scope, not the new one like I need it to. So clicking the same ng-clickable element still triggers the run() method on the previous grandparent's scope.
That all makes sense; but, is there a way to get the scope to point to the new dropped locations grandparent scope instead?
Thanks!
EDIT
The markup would be something like the following where <g-directive> is treated as a grandparent because it uses transclude on its template, ultimately wrapping the child directives:
<g-directive>
<child-directive></child-directive>
<another-child-directive></another-child-directive>
<yet-another-child-directive></yet-another-child-directive>
</g-directive>
<g-directive>
<c-child-directive></c-child-directive>
<c-another-child-directive></c-another-child-directive>
<c-yet-another-child-directive></c-yet-another-child-directive>
</g-directive>
That's the reason for the $scope.$parent.$parent.g on the child directives/components.
A child component can be dragged and then dropped into another <g-directive> but it's controller still points to its original grandparent (original <g-directive>'s controller scope variable). I want it to point to the new grandparent is was dropped into, essentially resetting it's scope to the newly placed scope.
<g-directive some-attr=1>
<child-directive></child-directive some-attr=1>
<another-child-directive></another-child-directive some-attr=1>
<yet-another-child-directive></yet-another-child-directive some-attr=1>
</g-directive>
<g-directive some-attr=2>
<child-directive></child-directive some-attr=2>
<another-child-directive></another-child-directive some-attr=2>
<yet-another-child-directive></yet-another-child-directive some-attr=2>
</g-directive>
Each can have different listener for broadcast and emit.
if the directives are repeated through ng-repeat then the $index can be that attribute.
Hope this helps.
I would like to know if there is a way to access the $scopes variables using the $rootScope such that if a function is defined in scope I can invoke it using $rootscope to or if there is a variable defined using $scope.var1 I could access it using $rootScope to
Every scope have a two property references to its child scopes, namely: $$childHead and $$childTail. Additionally every scope object has $$nextSibling and $$prevSibling properties pointing to same-level scope sibling instances. Having this properties you can travers all child scopes horizontally or vertically. Depending why you need to do it on each step you would check for necessary scope property or method.
That being said, I can't see real business-logic application for such child scope traversal, except for logging/debugging purposes, for example to build scope hierarchy tree, etc.
I am wondering how I can add a value to the scope from a function outside the controller. I have a series of functions in my controller file, which I would like to keep it separately outside a controller method, so that it can be accessed by different controllers. When the last function gets the value, I want to add it to the scope. Can anybody give me some input into this issue. Thanks
Angular $scope is not supposed to be accessed from outside. Use service/factory/provider to share data between controllers.
Say, define a factory with get/set functions. set the value in some controller and get it from somewhere else. $scope is not supposed to be passed around.
I know you may have seen this question before, but is there really an answer for it? I started to doubt it.
Simply, I am using controlleras syntax as recommended, I have no problem accessing parent controller members form within the view, but I cannot do it from the constructor function of my child scope. And here is some code from what I am having right now:
myapp.controller("ParentController", function() {
this.selectedItem = {
Id: 1,
name: 'item1'
};
this.setSelectedItem = function(item) {
this.selectedItem = item;
//do other stuff
}
});
myapp.controller("ChildController", function() {
this.onItemChanged = function(newItem) {
//How can I call the parent controller instance from here
}
});
Also please notice that I want to call the 'updateSelectedItem' function from my child controller in away that the 'this' keyword will refer to the parent controller instance not the child, because I want to change the parent controller instance, so how should I do this?
To answer your question as clearly as possible, you first must have a bit of background on how the Controller-As syntax actually works.
Using Controller-As does not mean that you are not using $scope. In reality, $scope still exists. Controller-As is shorthand which creates an object on $scope and attaches the properties assigned via this to that object. On the view side, this object is explicitly bound to all the controls. you could still reference $scope.vm.property. However, since $scope is implicit in this scenario, it is not necessary to create a dependency to it.
Accessing the properties of the vm object of the parent controller in a nested scenario is still possible, but only if each controller is referenced by a different name. If your objects are outerScope and innerScope, then inside the HTML template of innerScope, you can still refer to outerScope.someProperty.
If, however, all controllers are named the same (i.e. vm), then the only way to access the parent controller would be through a property of the child scope which is aliased to a $scope property, introducing the $scope dependency.
In practice, whenever you have a controller within another controller, it's much cleaner for the innermost item to be a directive which wraps its own content, and explicitly defines which variables it needs through an Isolate Scope. However, whenever this is not necessary, the fallback should be for inner controllers to be named uniquely from outer controllers.
I have two custom element directives:
<my-directive-parent></my-directive-parent> //only one
and
<my-directive-child></my-directive-child> //variable count
The my-directive-parent directive has its own controller and templateUrl properties defined in its directive definition object. The my-directive-child directive has its own link, scope, templateUrl and require properties defined in its directive definition object. The fourth parameter passed into the link function is the parent my-directive-parent's controller. This is working as expected.
Based on user input, instances of my-directive-child are appended to or removed from the parent my-directive-parent DOM via the my-directive-parent's controller. Since I'm using ngView for the top-level page, changing pages results in Angular automatically cleaning up the various directives and their controllers of the top-level page. Upon returning, the controller for the page re-runs, but the user appended views do not show up (since they were previously wiped out automatically by Angular). I'm using a service which holds the data representing the collection of my-directive-child instances that were previously added.
My issue lies in restoring the my-directive-child directives based on this cached service data. Currently, when the my-directive-parent directive's controller is run, I'm getting the service data array that represents the instances to be added, looping through it, and adding a new my-directive-child instance to the DOM. This is working, but upon restoring each instance I need to pre-populate it with data that was previously entered by the user (of which is recorded in the service). Currently, when adding to the DOM this way each instance is in a "blank" state instead of a desired pre-populated state.
So I have the data needed to recreate the child directive instances, but I'm unable to pre-populate them with the necessary data.
I've tried to place a custom attr on the my-directive-child in an effort to forward the data to the instance's scope, but I learned from Angular's API docs that:
The new scope rule does not apply for the root of the template since the root of the template always gets a new scope
Questions:
Is my approach wrong? What should I be doing?
Is there a way to pass attrs defined on the actual element directive into the directive's scope that represents the inner template HTML?
How do I ensure a custom directive within a custom directive properly pre-populates itself?
Thank you in advance for any ideas, answers, or thoughts that might lead to a solid solution.