I want that any element with title
attribute behaves like an uibTooltip
atribute (from UI Bootstrap module). So, I created a simple directive that automatically puts this atribute and removes that other one, like this:
angular.module( 'ui.bootstrap.tooltip' ) .directive( 'title', function( $compile ) { return { restrict: 'A', link: function( scope, elem, attrs ) { attrs.$set( 'uibTooltip', attrs.title ); $compile( elem.removeAttr( 'title' ) )( scope ); } }; } );
It converts the attributes and then it compiles again.
The problem appears, for example, in this element (in Bootstrap design):
<div ng-controller="ButtonController as vm"> <button type="button" class="btn btn-default" title="Add" ng-click="vm.add()"><span class="glyphicon glyphicon-plus"></span></button> </div>
With appropriate controller:
angular.module( 'app' ) // Whatever name .controller( 'ButtonController', function() { var vm = this; vm.add = function() { console.log( 'Added!' ); } } );
Since it recompiles, ngClick
function executes twice on click.
Which is the way for change element's attributes before compilation?
Re-compiling an already compiled element is not supported (and can lead to all sorts of problems, including memory leaks). What you can do instead, is specify a high-priority, terminal directive, switch the attributes and then continue the compilation starting from your directive's priority.
See https://github.com/angular/angular.js/issues/15270#issuecomment-253900234 for more details on how you can do this.
It is not a solution. The troubles is only in ngClick
, ngDblClick
, ngMouseenter
... event attributes.
It is not a solution. The troubles is only in ngClick, ngDblClick, ngMouseenter... event attributes.
Not sure what you mean 馃槙
Here you have an JSFiddle example. Update with your suggestion and share what you are exactly recommending, please.
The problem is 2 console logs on one click.
The priority on your directive override for ui.bootstrap.tooltip
needs to be very high (e.g. 2000), and it needs to be a terminal directive. The reason you're getting a double compile issues is because you're running $compile
again on the ENTIRE element after the framework has already compiled it for you. However, if you set priority to something very high, and set the directive to terminal, then it will ONLY compile the "decorator" directive which changes title
to uib-tooltip
. Then it will stop, due to the terminal flag. You can then manually compile the rest of the directives on the element via the $compile
service. Just ensure you set the maxPriority
argument to whatever high number you used on the directive override. That way the decorator directive will not be recompiled. This will compile all remaining elements on the directive, but NOT the decorator directive which has already been compiled by the angular framework.
For more info, see the usage section here: https://docs.angularjs.org/api/ng/service/$compile
Fixed your jsFiddle
Nice! It is running well! Take updated JSFiddle example.
Thanks!
The solution is fantastic, but there is a problem with ngRepeat
directive when the affected element is a child of repeated parent. I forked the JSFiddle test: here.
@Miqueliu, I'd be glad to take a look at it, but this isn't really the place for debugging. Unless you think this is actually a bug in the framework (which I don't think it is, I think it's something about the transclusion) you should do a stack overflow.
Ok. I will. Thank you.
In Stack Overflow, it is said that the ngRepeat directives conflict against terminal
property (of directives definition).