should I destroy directive scope or angular will do it - javascript

Could you please explain me one thing. Imagine we have directive called "myDirective". Here is html:
<div my-directive>
</div>
When we remove this div from DOM, will angular destroy scope of myDirective and its watchers or I have to listen the event "$destroy" on div DOM element and inside the listener to call scope.$destroy?

Usually when you remove a div from DOM, angularJS automatically deallocates events and destroys the scope, even if you don't listen to $destroy event.
So why you should use $destroy? You should use it to manually deallocate some non angularJS events and plugins (e.g. if you create a 'Kendo Grid' inside myDirective you need to destroy it inside the $destroy function using the plugin function to destroy it).
I suggest also to set all references to objects in the scope to null (best practice).

Related

ng-if not updating on scope destroy

I have an isolate scope directive. In this directive's link function I am compiling an html template and appending it to the document body.
const template = `<div ng-if="vm.open"></div>`;
body.append(template);
I have a button that toggles the vm.open flag on an ng-click. This works fine to show/hide my div. However, when I press the back button, my scope destroy event handler gets called and sets the vm.open to false. But in my DOM vm.open is still true.
Is this because ng-if made a new scope and since my directive is the 'parent' it doesn't destroy the ng-if's scope? I found another stackOverflow thread where using ng-show fixes this issue, which it does. But I would like to understand why it doesn't work with an ng-if.
try with
*ngIf={{vm.open}}

Why does my ready function always run when controller or directive reinisilize

When my controller or directive reinisilize angular.element(document).ready(function(){...}); function always runs. Why?
I have two controllers and one directive. I change value from parent controller which assign to ng-repeat. Whenever I change this variable, controller reinsilize and ready function recall too.
See this link: angualr ready function
Your code is set up such that you are destroying and recreating things when you click the "change index" button:
that.changeIndex = function(){
that.arr = [{name : g++}];
that.isValid = !that.isValid;
}
ng-repeat destroys and recreates your myCon2 controllers when you create a new arr array:
<div ng-repeat="m in con.arr track by m.name" ng-controller="myCon2 as con1">
And ng-if destroys or recreates your my-dir directive when you change isValid:
<div my-dir ng-if="con.isValid">hey directive!!!!</div>
The controller and directive both attach a handler to document ready, which will run as long as the document is ready (not just as soon as it becomes ready). This makes sense because if your code loads after the document initially becomes ready, you'd usually still want it to run.
By the way, you shouldn't need to use document ready inside Angular controllers and directives. You can put your initialization code at the top of them, or you can use ng-init.

Angular.js $scope and dom element

How does angular keep track of which $scope is related to which element? I have a few theories:
angular element keeps scope object as property
angular saves each scope in cache with the relationship with element
angular searches each ng-scope, and magically find element
For example, I have an element with $scope, and I want to change dom hierarchy of this element (moving to outside of the outer controller). How is scope affected by this action?
If you have an angular app, and your HTML looks something like this:
<div ng-controller="OuterController">
...
<div ng-controller="InnerController">
<div id="wrapper">
<span>An Element</span>
</div>
</div>
</div>
And you move the <span> out of the #wrapper div, it's still within the context of both OuterController and InnerController. However, if you move it up to where the ... is, only the OuterController's context applies.
Each controller has its own context, and that context extends down into all child-elements recursively, even if a new controller is present, at which point, both controllers are in-scope.
This is true whether the element is moved dynamically with Javascript or otherwise. Angular keeps track of most context internally.

Updating Angular view model on button click

I'm trying to understand how Angular data binding works. I have created this sample that displays {{values.count}} inside a span element:
<body ng-app="testApp" ng-controller="testCtrl as values">
<span>Count = {{values.count}}</span>
<button id="incr">++</button>
</body>
<script>
testApp = angular.module("testApp", []);
testApp.controller("testCtrl", function () {
var values = this;
values.count = 5;
$("#incr").on('click', function () {
values.count += 1;
});
});
</script>
If I click on the button, values.count is incremented, but the span is not updated. I can get it to work if I place a ng-click="values.Increment()" on the button and create a values.Increment method in the controller, but what is the difference that makes one work and the other not?
You are doing it the wrong way. When using angular, you don't need to bind event handlers/access DOM elements for this purpose. Use built-in ng-click directive.
<button ng-click="values.incr()">++</button>
and
values.incr = function(){
values.count++;
}
You could even do it inline, <button ng-click="values.count = values.count+1">++</button>
The reason why your code did not update DOM is because of the way angular works. Even though you are incrementing the value inside the manually bound event handler angular is unaware of the update and it does not update DOM binding with the new value. Though a bad practice in your specific case you can achieve that by doing $scope.$apply() (but ofcourse you need to inject $scope in your controller) as well inside the event handler to manually invoke the digest cycle. General thumb rule when working with angular is the controller do not access DOM directly, Instead it just sets up data for the view and with the help of bindings and other built-in or custom directives you get the intended behavior in your application.
Read about scope life cycle and digest cycle

AngularJS : Why is my $scope not shared with a child directive

I have created two directives, one of them is used within the other and it has been created just for the matter of seperation of concerns.
<div class="docinputContainer">
<textarea></textarea>
<easy-table></easy-table>
</div>
I have omitted the scope property on both of them, therefore i would have thought that i could bind a keydown eventon my parent directive, which then could call a $scope method from the child directive:
// parent
element.bind('keydown',function(e){
$scope.save();
});
// easyTable
$scope.save = function(){
// ...
}
However, this method is unknown in my parent directives $scope.
Now i have some questions:
Why is this? Shouldn't both directives share a scope?
What would be the best solution to this?
I know i could do one of the following:
Broadcast an event
Use a shared service to trigger an event
Concatenate both directives
I would prefer to share the scope, though. Any help is appreciated
Solution
I bypassed my issue by binding the element to a scope property on the parent directive, then binding the keydown event in easyTable itself, instead of the parent one.

Categories