AngularJS指令转换部件绑定

时间:2013-08-30 21:13:39

标签: angularjs angularjs-directive

我想在transcluded部分中使用指令,转换内容和调用指令的控制器方法:

<mydirective>
  <div ng-click='foo()'>
    click me
  </div>
</mydirective>


app.directive "mydirective", ->

  return {
    restrict:  'EACM',
    transclude: true
    template: "<div ng-transclude></div>"
    scope: { } #required: I use two way binding on some variable, but it's not the question here

    controller: [ '$scope', ($scope)->
      $scope.foo = -> console.log('foo')
    ]
  }

plunkr here.

我该怎么办呢?

3 个答案:

答案 0 :(得分:6)

我有一个不同的答案,这不是一个黑客,我希望它会被接受..

请参阅my plunkr了解实时演示

这是我对指令的使用

<div custom-directive custom-name="{{name}}">      
  if transclude works fine you should see my name right here.. [{{customName}}]
</div>

注意我在指令中使用customName并为其指定一个值作为指令范围的一部分。

这是我的指令定义

angular.module('guy').directive('customDirective', function($compile, $timeout){
    return {
      template : '<div class="custom-template">This is custom template with [{{customName}}]. below should be appended content with binding to isolated scope using the transclude function.. wait 2 seconds to see that binding works</div>',
      restrict: 'AC',
      transclude: true, 
      scope : {
        customName : '@'
      }, 
      link : function postLink( scope, element, attrs, dummy, transcludeFn ){
          transcludeFn( scope, function(clone, innerScope ){
             var compiled = $compile(clone)(scope);
             element.append(compiled);
          });

         $timeout( function(){

            scope.customName = 'this stuff works!!!';

          }, 2000);
      }
    }
  });

请注意,我将在2秒后更改范围上的值,以便显示绑定有效。

在网上阅读了很多内容后,我理解了以下内容:

  • ng-transclude指令是转换的默认实现,可由用户根据用例重新定义
  • 重新定义翻译意味着angular将在每个$digest
  • 上使用您的定义
  • 默认情况下 - transclusion创建一个新的范围,它不是隔离范围的子节点,而是兄弟节点(因此黑客工作)。如果您重新定义了转换过程,则可以选择在编译已转换内容时使用的范围。 - 即使新范围是STILL创建的,似乎
  • transclude功能没有足够的文档。我甚至没有在文档中找到它。我在another SO answer
  • 中找到了它

答案 1 :(得分:3)

这有点棘手。被转换的范围不是指令范围的子代,而是兄弟姐妹。因此,为了从transcluded元素的foo访问ng-click,您必须将foo分配给正确的范围,即指令范围的兄弟。请务必从link函数访问已转换的范围,因为它尚未在controller函数中创建。

Demo link

var app = angular.module('plunker', []);
app.directive("mydirective", function(){
  return {
    transclude: true,
    restrict: 'EACM',
    template: "<div> {{ name }} <br/><br/> <div ng-transclude> </div></div>",
    scope: { },
    link: function($scope){
      $scope.name = 'Should change if click below works';
      $scope.$$nextSibling.foo = function(){
        console.log('foo');
        $scope.name = 'it works!';
      }
    }
  }
})

另一种方法是将foo分配给父范围,因为两者都是原型范围的继承,即

$scope.$parent.foo = ...

答案 2 :(得分:0)

从技术上讲,如果删除scope: { },那么它应该可以工作,因为该指令不会创建一个隔离的范围。 (顺便说一句,您需要添加restrict: "E",,因为您将指令用作元素)

我认为从指令调用父作用域中定义的动作更有意义,而不是从父作用域调用指令中的动作。 Directive应该是自包含可重用。指令中的操作不应该从外部访问。

如果你真的想这样做,你可以尝试通过调用$scope.$broadcast()发出一个事件,并在指令中添加一个监听器。希望它有所帮助。