自定义指令的控制器不适用于ng-repeat?

时间:2017-08-21 16:10:51

标签: javascript angularjs angularjs-directive

我正在尝试构建2个自定义指令my-tile和my-tile-item。

“my-tile”是接受数据数组参数的主要指令。

“my-tile-item”表示“my-tile”中的单个图块。

但my-tile-item控制器的btnOkClick()方法不起作用。

代码:

https://codepen.io/anon/pen/zdWgVG

HTML:

<div my-tile tiles="mainCtrl.tiles"></div>

my-tile模板:

<script type="text/ng-template" id="myTile.html">
    <div my-tile-item ng-repeat="tileItem in myTileCtrl.tiles" class="my-tile">
        <div>{{tileItem.id}}</div>
        <button ng-click="myTileItemCtrl.btnOKClick()">OK</button>
    </div>

</script>

my-title指令:

angular.module('app').directive('myTile',
        [
            myTile
        ]);


    function myTile() {
       return {
           restrict: 'AE',
           scope: {
             tiles: '='
           },

           controller: ['$scope', MyTileController],
           controllerAs: 'myTileCtrl',


           templateUrl: 'myTile.html',

           link: function (scope, iElement, iAttrs) {
               console.log('abc');
           }
       };


       function MyTileController($scope) {
           var ctrl = this;
           ctrl.tiles = $scope.tiles;
       }

    }

my-tile-item指令:

angular.module('app').directive('myTileItem',
        [
            myTileItem
        ]);


    function myTileItem() {
        return {
            restrict: 'AE',
            scope: {

            },

            controller : ['$scope', MyTileItemController],
            controllerAs : 'myTileItemCtrl',

            link: function (scope, iElement, iAttrs) {

            }
        };


        function MyTileItemController($scope) {
            var ctrl = this;

            ctrl.btnOKClick = function () {
                alert('OK Clicked'); // ********* does NOT work *************
            }
        }


    }

3 个答案:

答案 0 :(得分:2)

它按预期工作。由于my-tile-item指令具有自己的独立范围和自己的控制器并不意味着,指令范围将应用于该元素。当指令有自己的templatetranscluded content时,指令的范围将使用element进行编译。因此,在my-title-item指令中,您没有template,这就是为什么指令不会将指令范围应用于托管它的元素。

要解决您的问题,您可以在从myTileItemCtrl指令生成内部模板后,在元素上使用my-title-item范围。然后,您可以考虑将item作为范围绑定从my-title-item指令传递给my-tile

<script type="text/ng-template" id="myTile.html">
    <div ng-repeat="tileItem in myTileCtrl.tiles" class="my-tile">
       <my-tile-item item="tileItem"></my-tile-item>
    </div>
</script>

my-item指令

function myTileItem() {
    return {
        restrict: 'AE',
        scope: {
          item: '<'
        },
        template: `
          <div>{{item.id}}</div>
          <button ng-click="myTileItemCtrl.btnOKClick()">OK</button>
        `,
        //...
    }
}

Forked Codepen

通过上面的模板结构,你也实现了Smart and Dumb Component Pattern,其中父亲几乎负责主要责任,而子女只接受绑定并在视图中呈现它。

答案 1 :(得分:0)

(function () {
    'use strict';

    angular.module('app').directive('myTileItem',
        [
            myTileItem
        ]);


    function myTileItem() {
        return {
            restrict: 'AE',
            link: function (scope, iElement, iAttrs) {
              scope.btnOKClick = function () {
                alert('OK Clicked');
            }
            }
        };
    }
})();

将btnOnClick移动到tileItem指令的链接功能,并删除范围:{}它将开始工作。并将<button ng-click="mytileItemCtrl.btnOKClick()">OK</button>更改为<button ng-click="btnOKClick()">OK</button>

答案 2 :(得分:0)

你有一些问题。

我已经改变了您的代码,现在它正在工作:https://codepen.io/anon/pen/jLxNvE

第一个错误的修复可能是删除item指令中的隔离范围,只需删除item指令的块scope即可。 通过这种方式,您的item指令将访问父级的范围,并可以覆盖该范围,添加新属性(作为您的函数)。

但这是错误的解决方案。

遵循最佳方法,而不删除项目指令中的孤立范围

您没有为item指令定义模板。您应该为您尝试实现的目标添加模板,因为如果您隔离范围,那么您的控制器只能在该指令的模板中访问,而无需查看父级的范围。没有相应的模板,该功能无法在那里调用。

然后在这些情况下最好的做法是你应该在item指令定义中提供一个scope参数,这实际上就是item(我用双向数据绑定做了但我不知道你想要什么do,所以根据您的要求更改绑定)。

这样一切都会正常。

相关问题