Filippo oretti
Filippo oretti

Reputation: 49843

AngularJS multiple directives on same element, $compile:multidir ERROR

Here is the plunkr: http://plnkr.co/edit/CzcVzKSvpKJTuTKARVJz?p=preview

and this is my simple code:

.directive('ngB', [function () {
    return {
      'restrict': 'A',
      'scope': {
        'ngB': '='
      },
      'link': function($scope, el) {

        var clss = 'b'
          , go = function () {

            if ($scope.ngB) {

              el.removeClass('a');
              el.addClass(clss);
            } else {
              el.removeClass(clss);
            }
          };

        $scope.$watch('ngB', function () {
          go();
        });
      }
    };
  }])
  .directive('ngF', [function () {
    return {
      'restrict': 'A',
      'scope': {
        'ngF': '='
      },
      'link': function($scope, el) {

        var clss = 'f'
          , go = function () {
            if ($scope.ngF) {

              el.removeClass('a');
              el.addClass(clss);
            } else {
              el.removeClass(clss);
            }
          };

        $scope.$watch('ngF', function () {
          go();
        });
      }
    };
  }]);


  //view.html
  <span ng-b="2 > 1" ng-a="1 > 2">here</span>

It returns this error in console: https://docs.angularjs.org/error/$compile/multidir

How can i fix this without removing one of the directives from the elmeent

thank you a lot.

Upvotes: 2

Views: 2028

Answers (2)

New Dev
New Dev

Reputation: 49590

As suggested above, you cannot have two directives creating multiple scopes, whether isolate or child, on the same element.

You don't always need an isolate scope.

if all you are doing is observing a change in an attribute value:

<span ng-f="{{1 < foo}}"></span>

Then you could pick up the changes with attrs.$observe:

link: function(scope, element, attrs){
  attrs.$observe("ngF", function(v){
     // do something
  });
}

If, however, you are watching for a change in the model value assigned to the attribute or an expression result

<span ng-f="foo"></span>
<span ng-f="foo === 10"></span>

which seems to me to be the case, you can use $parse service and $watch for changes in the value.

link: function(scope, element, attrs){
   var parsed = $parse(attrs.ngF);
   scope.$watch(function(){
      return parsed(scope);
   },
   function(v){
     // do something
   });
}

Upvotes: 2

Pankaj Parkar
Pankaj Parkar

Reputation: 136174

As per angular Design you can't have an two isolated scope directive applied on the same DOM element (Reference Link) ()

If you look at the AngularJS documentation, you'll see that they do recommend using isolate scopes in certain situations:

Best Practice: Use the scope option to create isolate scopes when making components that you want to reuse throughout your app.

I would prefer you to use transclusion or place directive in nested manner, in that way it would work

HTML

<span ng-b="2 > 1">Outside
   <span ng-a="1 > 2">Inside
</span>

Plunkr

Hope this could help you, Thanks.

Upvotes: 1

Related Questions