使用ng触发功能在ng Transclude中单击

时间:2013-12-08 08:33:43

标签: angularjs angularjs-directive angularjs-ng-repeat angularjs-ng-click transclusion

在使用ngRepeat时,我有一个无序列表,从数组中加载了四个项目。列表项中的锚标记在ngClick属性中具有触发消息的功能。使用时函数调用效果很好:

<ul>
  <li ng-repeat="n in supsNames">
    <a ng-click="myAlert(n.name)">{{n.name}}</a>
  </li>
</ul>

我创建了一个简单的指令,用于插入包含列表项的无序列表。列表加载得很好,但我之前提到的功能相同并不会启动。代码如下:

<div list items="supsNames">
  <a ng-click="myAlert({{item.name}})">{{item.name}}</a>
</div>

这是我的javascript和angularjs代码:

var app = angular.module('myapp', []);

app.controller('myCtrl', function($scope) {

$scope.title = 'ngClick within ngTransclude';
$scope.supsNames = [
    {"name" : "Superman"},
    {"name" : "Batman"},
    {"name" : "Aquaman"},
    {"name" : "Flash"}
  ];

  $scope.myAlert = function(name) {
    alert('Hello ' + name + '!');
  };
});

app.directive('list', function() {

return {

restrict: 'A',
scope: {
  items: '='
},
templateUrl: 'list.html',
transclude: true,
link: function(scope, element, attrs, controller) {
  console.log(scope);
}

};

});

如果你想看看我试图做什么,我也有一个plnkr: http://plnkr.co/edit/ycaAUMggKZEsWaYjeSO9?p=preview

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

我得到了plunkr工作。我不确定它是不是你正在寻找的。我复制了下面的主要代码更改。

以下是plunkr:

http://plnkr.co/edit/GEiGBIMywkjWAaDMKFNq?p=preview

修改后的指令现在看起来像这样:

app.directive('list', function() {
  return {
    restrict: 'A',
    scope: {
      items: '=', 
      ctrlFn: '&' //this function is defined on controller
    },
    templateUrl: 'list.html',
    transclude: true,
    link: function(scope, element, attrs, controller) {

      //directive fn that calls controller defined function
      scope.dirFn = function(param) {
        if(scope.ctrlFn && typeof scope.ctrlFn == 'function') { //make sure its a defined function
          scope.ctrlFn( {'name': param} ); //not sure why param has to be passed this way
        }
      }

    }

  };

});

以下是在绑定到控制器的html文件中调用它的方式:

<div list items="supsNames" ctrl-fn="myAlert(name)">
  <a ng-click="dirFn(item.name)">{{item.name}}</a>
</div>

我认为之前发生的事情是你试图在指令的隔离范围内使用控制器中定义的函数,因此它不起作用 - 该函数在指令中未定义。所以我所做的是在指令中添加了另一个参数,该指令接受方法绑定(我认为这就是它所谓的)与'&amp;'。

所以基本上你将控制器方法传递给指令,然后通过创造性地命名为“dirFn”的指令定义方法调用该方法。我不知道这本来是最好的方式,但我已经在现有的项目中使用了它,效果很好;)

答案 1 :(得分:1)

您需要将该函数传递给指令

scope: {
   items: '=', 'myAlert': '='
},

答案 2 :(得分:0)

指令模板中的 ng-repeat 插入一个新范围,需要手动调用transclude funcion才能工作。我建议删除 ng-repeat 并手动传递控制器范围的副本并在每个副本上设置项目:

for(var i=0,len=scope.items.length;i<len;i++){
    var item=scope.items[i];
    var itemScope=scope.$parent.$new();
    $transcludeFn(itemScope, function (clone,scope) {
                // be sure elements are inserted
                // into html before linking
                scope.item=item;
                element.after(clone);
    });
  };

我编辑了pluker,我希望这可能会有所帮助:http://plnkr.co/edit/97ueb8SFj3Ljyvx1a8U1?p=preview

有关移植的详情,请参阅:Transclusion: $transcludeFn