Broadcast content requires a forward directive controller

I have a directive that passes its contents. And in the transmitted content there is a directive that requires the controller of the forwarding directive. This causes an error if I create the transclude function in the forwarding directive. I think this is due to the fact that the transclosed content is cloned when you provide the transclude function ( https://github.com/angular/angular.js/blob/master/src/ng/compile.js#L846 ).

I also have a plunker describing my problem: http://plnkr.co/edit/rRKWW6zfjZuUiw1BY4zs?p=preview

What I want to do is that I want to overlap the content and analyze all the broadcast content, and then put it in the right place in the DOM and compile it myself. The enclosed content is actually a configuration of my directive.

I also tried to clear the cloned array that I received in the cross-link function, because in fact I do not need to automatically translate the contents. I just need to parse it and translate it manually to a later point in time. Angular does not need to do anything with my transferred content. But this does not work, because the directives are already identified when the forwarding function is called. So when I empty the array, I get an error here ( https://github.com/angular/angular.js/blob/master/src/ng/compile.js#L961 ).

Yours faithfully,

Daan

+4
source share
3 answers

When you use require: "^controller", you tell Angular that the directive requires that it controllerbind to the ancestor DOM element when the link function is run.

When you switch without using the ngTransclude directive, your parent directive reference function gets the transclude method passed. (You already knew that, it's just for completeness.) This forwarding method does the following:

  • Retrieves content for navigation
  • If a cloneAttachFnwas passed, clone the content and call cloneAttachFn
  • $compile(), ( ) , ( , $ ).

transclude ( DOM), . , .

, kmBar require: "^kmFoo", DOM, kmFoo.

- kmFoo () , detach it.

( remove) . , . AngularJS, jQuery , jqLite.

Plunk

app.directive('kmFoo', function() {
  return {
    restrict: 'A',
    scope: true,
    template: '<div></div>',
    transclude: true,
    controller: function() {
      // ...
    },
    link: function(scope, $element, attrs, ctrl, transcludeFn) {
      console.log('linking foo');
      // We are going to temporarily add it to $element so it can be linked,
      //  but after it linked, we detach it.
      transcludeFn(scope, function(clone) {
        console.log('transcluding foo');
        $element.append(clone);
        c = clone;
      }).detach();// <- Immediately detach it
    }
  };
});

app.directive('kmBar', function() {
  return {
    restrict: 'A',
    scope: true,
    require: '^kmFoo',
    link: function(scope, $element, attrs, fooCtrl) {
      console.log('linking bar');
      // Right now it a child of the element containing kmFoo,
      //  but it won't be after this method is complete.
      // You can defer adding this element to the DOM
      //  for as long as you want, and you can put it wherever you want.
    }
  };
});
+8

-, ? ?

app.directive('kmFoo', function() {
  return {
    'restrict': 'A',
    'scope': true,
    'controller': function() {
      this.tryMe = function() { console.log("Success!") };
    },
    'link': function(scope, element, attrs, ctrl) {
      console.log('linking foo');
      var innerHtml = element.html();
      // do something with innerHtml
      element.html("<div>Empty</div>");
    }
  };
});

app.directive('kmBar', function() {
  return {
    'restrict': 'A',
    'scope': true,
    'require': '^kmFoo',
    'link': function(scope, element, attrs, fooCtrl) {
      fooCtrl.tryMe();
    }
  };
});

fooController transclude kmFoo, element.controller() .

app.directive('kmFoo', function() {
  return {
    'restrict': 'A',
    'scope': true,
    'template': '<div ng-transclude></div>',
    'transclude': true,
    'controller': function() {
      this.tryMe = function() { console.log("Success!") };
    },
    'link': function(scope, $element, attrs, ctrl, transcludeFn) {
      console.log('linking foo');
      // when you put the transclude function in comments it won't throw an error
      transcludeFn(scope, function(clone) {
        console.log('transcluding foo');
      });
    }
  };
});

app.directive('kmBar', function() {
  return {
    'restrict': 'A',
    'scope': true,
    'template': "<button ng-click='tryMe()'>Feeling lucky?</button>",
    'link': function(scope, element, attrs) {
      scope.getFooCtrl = function() { 
        return element.parent().controller('kmFoo'); 
      };
      console.log('linking bar');
      console.log('parent not yet known: ' + element.parent().toString());
    },
    'controller': function($scope) {
      $scope.tryMe = function() {
        $scope.getFooCtrl().tryMe();
      };
    }
  };
});

plnkr.

0

To accomplish this without displaying it in the DOM, you can use

 transclude: 'element' 

in the second directive.

This will avoid the use of some tricks to get the necessary information.

app.directive('kmFoo', function() {
  return {
    'restrict': 'A',
    'scope': true,
    'template': '<div ng-transclude></div>',
    'transclude': true,
    'controller': function() {

    },
    'link': function(scope, $element, attrs, ctrl, transcludeFn) {
      console.log('linking foo');
      // when you put the transclude function in comments it won't throw an error
      //transcludeFn(scope, function(clone) {
      //  console.log('transcluding foo');
      //});
    }
  };
});

app.directive('kmBar', function() {
  return {
    'restrict': 'A',
    'scope': {},
    'require': '^kmFoo',
    'link': function(scope, $element, attrs, fooCtrl) {
      console.log('linking bar');
    }
  };
});

app.directive('kmBarWithElement', function() {
  return {
    'restrict': 'A',
    'scope': {},
    'transclude': 'element',
    'require': '^kmFoo',
    'link': function(scope, $element, attrs, fooCtrl, transclude) {
      transclude(function(clone) {
        console.log('here the element: ', clone);
      });
    }
  };
});

Here is a working example: http://plnkr.co/edit/lbT7oz74Yz7IZvEKp77T?p=preview

0
source

Source: https://habr.com/ru/post/1538434/


All Articles