【问题标题】:AngularJS directive transclude part bindingAngularJS 指令 transclude 部分绑定
【发布时间】:2013-08-30 21:13:38
【问题描述】:

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

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

请问我该怎么做?

【问题讨论】:

  • 嗨,我现在也在尝试做同样的事情。您是否尝试过直接使用 transclude 功能?

标签: angularjs angularjs-directive


【解决方案1】:

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

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

【讨论】:

  • 绝对是要走的路。谢谢你的更新,我忘了我问了:)
【解决方案2】:

这有点棘手。被嵌入的作用域不是指令作用域的子作用域,而是兄弟作用域。因此,为了从被嵌入元素的ng-click 访问foo,您必须将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 = ...

【讨论】:

    【解决方案3】:

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

    我认为从指令调用父作用域中定义的动作比从父作用域调用指令中的动作更有意义。 Directive 应该是独立的可重复使用的。指令中的操作不应从外部访问。

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

    【讨论】:

    • 可以限制,刚刚做了一个 plunkr。我看到您的解决方案有效,但如果我想保留范围怎么办?我打算在同一个页面中多次使用该指令+已经使用它来绑定其他变量
    • 是否可以给嵌入元素我想要的范围或以某种方式访问​​指令范围?
    • @apneadiving 我认为从指令调用父作用域中定义的操作而不是从父调用指令中的操作是有意义的。指令应该是独立的和可重用的。不应从外部访问这些操作。
    猜你喜欢
    • 1970-01-01
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多