I have created a directive (ParentDir) that has it's own controller and whose template binds to this controller. It communicates with another directive (Child1) that has it's own controller which 'requires' the first parent directive. Below is a simplified example:
Module.directive("ParentDir", function () {
return {
templateUrl: '../ParentTemplate',
restrict: 'AEC',
scope: {
},
controllerAs: 'parCtrl',
bindToController: true,
controller: ['$scope', function ($scope) {
parCtrl= this;
parCtrl.title = "PARENT 1 TITLE";
}]}
Module.directive("Child1", function () {
return {
templateUrl: '../Child1Template',
restrict: 'AEC',
require: '^^ParentDir',
scope: {},
controllerAs: 'ch1Ctrl',
bindToController: true,
link: function ($scope, element, attrs, parCtrl) {
$scope.parCtrl= parCtrl;
},
controller: ['$scope', function ($scope) {
ch1Ctrl= this;
ch1Ctrl.title = "CHILD 1 TITLE";
}]}
ParentDir html:
<child1> </child1>
Child1 html:
{{parCtrl.title}}
{{ch1Ctrl.title}}
Finally my ParentDirective is initialized in something like this:
<div ng-animate-swap="trigger" class="swapclass">
<parent-dir></parent-dir>
</div>
I need the entire parent directive's template to slide in certain cases. I also use the directive in other places where I don't need this and I can use it as is. In the cases where I do need the slide animation, I place it inside an ng-animate-swap as shown above. The problem is that every time the swap trigger changes, a new parCtrl is initialized causing everything to be reset!
How can I use animate swap with a directive that has isolate scope and it's own controller, without reinitializing the controller everytime a swap occurs?
Directives, as we know, are high-level markers that tell Angular's compiler to attach a specified behavior to that HTML element. When a directive is put on the DOM, Angular's $compile
service matches directive names with their code, normalizes it and executes it.
However, ng-animate-swap
removes its element from the DOM before appending the new one.
This means your directives are being recompiled for each swap, and new isolate scopes are created each time the animation happens.
The solution to this depends on the functionality of your app, how large your templates are, and how often you need to do the animation (or what the animation entails):
One solution is to create another directive outside of the swap animation that holds parCtrl.title
and ch1Ctrl.title
(or whatever other variables you have) and then is able to pass that information down to child scopes through prototypical inheritance:
<swap-dir>
<div ng-animate-swap="trigger" class="swapclass">
<parent-dir></parent-dir>
</div>
<swap-dir>
This could also be done with a controller, perhaps much more easily. What you choose to do would depend on where you're getting your scope variables from and how many different elements you have on the page.
However, ng-animate-swap
creates its own scope, so while I believe this would work, the ever-fun JavaScript inheritance shenanigans could cause an issue here as well.
Another solution would be to skip ng-animate-swap
altogether and just animate the template element with regular old CSS transitions, although this depends on what you're doing and how you want it to look.