I am trying to implement a directive that replace a tag by a with ng-click in it. The ng-click call a function that replace the content of a div (always the same) with the content of another element, the id of which is passed as parameter. I managed to make it work, but only for the first click. After that, the page is reloaded and it seems that it is because ng-click isn't triggered, but the (empty) href attribute is.
the html code :
<!-- language: lang-html -->
<div id="uiMain" class="container">
Go to <go target="block01">01</go>, <go target="block02">02</go> or <go target="block03">03</go>
</div>
<div id="block01" class="block">
Go to <go target="block02">02</go> or <go target="block03">03</go>
</div>
<div id="block02" class="block">
Go to <go target="block01">01</go> or <go target="block03">03</go>
</div>
<div id="block03" class="block">
Go to <go target="block01">01</go> or <go target="block02">02</go>
</div>
and my directive :
.directive('go', function() {
return {
restrict: "E",
scope: {
target: "@"
},
transclude: true,
template: '<a href="" ng-click="displayBlock(\'{target}\')"><ng-transclude></ng-transclude></a>',
link: function (scope, element, attrs) {
scope.displayBlock = function() {
// Get the content of the target block
var content = angular.element(document.querySelector("#"+attrs.target));
// Get the main container
var mainContainer = angular.element(document.querySelector("#uiMain"));
// then replace the link with it
if (content !== null) {
//mainContainer.html($compile(content.innerHTML)($scope));
mainContainer.html(content.html());
}
};
}
};
});
I have tried putting my function back into the controller but he behavior is the same. I also tried to use $compile or $apply to make sure that the scope is up to date with the pasted html content : this doesn't work because the directives in my target block were already compiled.
Here is my plnkr for the whole code.
I want to be able to click the links to go back and forth, but for now there is something that stop the ng-click from firing more than once.
EDIT:
thanks to Mosh-Feu, i managed to make it work by adding ng-non-bindable
to all target element and changing my directive as follow :
.directive('go', function($compile) {
return {
restrict: "E",
scope: true,
transclude: true,
template: '<a href="" ng-click="displayBlock(\'{target}\')"><ng-transclude></ng-transclude></a>',
link: function (scope, element, attrs) {
scope.displayBlock = function() {
// Get the content of the target block
var content = angular.element(document.querySelector("#"+attrs.target));
// Get the main container
var mainContainer = angular.element(document.querySelector("#uiMain"));
// then replace the link with it
if (content != null) {
mainContainer.html(content.html());
$compile(mainContainer)(scope);
};
};
}
};
});
But Aditya Bhave solution is cleaner, so I will be using it. Thanks a lots guys !
The issue is, when we replace innerHTML of div with html(), it does not compile it as an angularjs code. The correct way is to use ng-templates.
Take a look at this Plunkr - http://next.plnkr.co/edit/x0TiUkka5nJwqB8K
Note - We can have more cleaner code, if we pass temmplateURL as a attribute to directive and then change it in onclick instead of using scope.$parent.