5

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

<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')
    ]
  }

在这里。

请问我该怎么做?

4

3 回答 3

6

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

查看我的 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
  • 默认情况下 - 嵌入会创建一个新范围,它不是孤立范围的子范围,而是兄弟范围(因此 hack 起作用)。如果您重新定义嵌入过程,您可以选择在编译嵌入内容时使用哪个范围.. - 即使仍然创建了一个新范围,它似乎
  • transclude 函数没有足够的文档。我什至没有在文档中找到它。我在另一个 SO 答案中找到了它
于 2014-09-22T15:57:44.473 回答
3

这有点棘手。被嵌入的作用域不是指令作用域的子作用域,而是兄弟作用域。因此,为了foong-click被嵌入的元素访问,您必须分配foo正确的范围,即指令范围的兄弟。一定要从link函数中访问被嵌入的范围,因为它还没有在controller函数中创建。

演示链接

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 = ...
于 2013-08-30T21:48:00.037 回答
0

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

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

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

于 2013-08-30T21:19:37.193 回答