Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Double compiling #15278

Closed
ghost opened this issue Oct 17, 2016 · 11 comments
Closed

Double compiling #15278

ghost opened this issue Oct 17, 2016 · 11 comments

Comments

@ghost
Copy link

ghost commented Oct 17, 2016

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?

@gkalpak
Copy link
Member

gkalpak commented Oct 17, 2016

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 #15270 (comment) for more details on how you can do this.

@gkalpak gkalpak closed this as completed Oct 17, 2016
@ghost
Copy link
Author

ghost commented Oct 17, 2016

It is not a solution. The troubles is only in ngClick, ngDblClick, ngMouseenter... event attributes.

@gkalpak
Copy link
Member

gkalpak commented Oct 17, 2016

It is not a solution. The troubles is only in ngClick, ngDblClick, ngMouseenter... event attributes.

Not sure what you mean 😕

@ghost
Copy link
Author

ghost commented Oct 17, 2016

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.

@Aaron-Pool
Copy link

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

@Aaron-Pool
Copy link

Fixed your jsFiddle

@ghost
Copy link
Author

ghost commented Oct 18, 2016

Nice! It is running well! Take updated JSFiddle example.

Thanks!

@ghost
Copy link
Author

ghost commented Oct 20, 2016

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.

@Aaron-Pool
Copy link

@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.

@ghost
Copy link
Author

ghost commented Oct 21, 2016

Ok. I will. Thank you.

@ghost
Copy link
Author

ghost commented Oct 27, 2016

In Stack Overflow, it is said that the ngRepeat directives conflict against terminal property (of directives definition).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants