如何修改指令中ng-repeat创建的每个元素的个别范围?

时间:2015-10-04 09:28:43

标签: javascript jquery html angularjs

我试图编写一个指令来简化Angular中的表格。我只是希望用户提供带有列表对象的指令以及html中每个列表元素的格式,如下面的my-table标记...

<h3>My Table</h3>
<div ng-controller='Ctrl as ctrl'>
<my-table items=ctrl.list>
    title: {{$item.title}}
    name: {{$item.name}}
</my-table>
</div> 

到目前为止,我已经得到了一些有效的答案here,但我需要添加更多功能,而且我遇到了问题。在下面的my-table指令中,您可以在link函数中看到html模板。如何在每个列表元素的各个范围上设置变量?当鼠标悬停在该元素上时(使用ng-mouseenterng-mouseleave),我应该可以修改它吗?我应该能够将它传递给我在模板中引用的table-edit-panel指令......

(function() {
    'use strict';

    angular
        .module('myApp')
        .directive('myTable', myTable);

    myTable.$inject = ['$compile'];

    function myTable($compile) {
        var directive = {
            transclude: true,
            scope: {    
                items: '='            
            },
            link: link  
        };
        return directive;

        function link(scope, elem, attr, ctrl, transclude) {

            scope.onMouseLeave = function(testvar) {
                testvar.state = "ready";
            };

            scope.onMouseEnter = function(testvar) {        
                testvar.state = "active";           
            };

            // not working, seems to be only one testvar rather than one for each element
            var template = 
                '<div ng-repeat="$item in items" ng-mouseenter="onMouseEnter(testvar)" ng-mouseleave="onMouseLeave(testvar)">' +
                    '<div class="row">' +                   
                    '<div class="col-md-10">' +
                        '<placeholder></placeholder>' +
                    '</div>' + 
                    '<div class="col-md-2">' +
                        '<table-edit-panel value="testvar"></table-edit-panel>' +
                    '</div>' +
                    '</div><hr/>' +
                '</div>';               

            var templateEl = angular.element(template);

            transclude(scope, function(clonedContent){
                templateEl.find("placeholder").replaceWith(clonedContent);

                $compile(templateEl)(scope, function(clonedTemplate){
                    scope.testvar = { state: "ready" }; // should be a testvar for each element of the list!
                    elem.append(clonedTemplate);
                });
            });
        }
    }
})();

您可以访问jsfiddle上的完整代码。您可以看到问题在于,使用我当前的方法,当我将鼠标悬停在一个列表元素上时,testvar变量会更改所有列表元素而不是我翻过的那个。

1 个答案:

答案 0 :(得分:1)

使用$item.testvar代替testvar,您可以访问每个项目的子范围。

 var template = '<div ng-repeat="$item in items" ng-init="$item.testvar.state = \'ready\'" ng-mouseenter="onMouseEnter($item.testvar)" ng-mouseleave="onMouseLeave($item.testvar)">' +
    '<div class="row">' +                   
    '<div class="col-md-10">' +
        '<placeholder></placeholder>' +
    '</div>' + 
    '<div class="col-md-2">' +
        '<table-edit-panel value="$item.testvar"></table-edit-panel>' +
    '</div>' +
    '</div><hr/>' +
'</div>';   

但是,在这种情况下需要初始化这些状态变量。我添加了ng-init来实现这一目标。虽然这是ng-init的少数几个预期用途之一,但我认为在控制器中初始化状态变量更为清晰。

更新(此次仅使用范围):

var template = 
    '<div ng-repeat="$item in items" ng-init="testvar.state = \'ready\'" ng-mouseenter="onMouseEnter(testvar)" ng-mouseleave="onMouseLeave(testvar)">' +
    '<div class="row">' +                   
    '<div class="col-md-10">' +
        '<placeholder></placeholder>' +
    '</div>' + 
    '<div class="col-md-2">' +
        '<table-edit-panel value="testvar"></table-edit-panel>' +
    '</div>' +
    '</div><hr/>' +
'</div>'; 

var templateEl = angular.element(template);

    transclude(scope, function(clonedContent){
        templateEl.find("placeholder").replaceWith(clonedContent);

        $compile(templateEl)(scope, function(clonedTemplate){

            // REMOVED THIS LINE:
            // scope.testvar = { state: "ready" };
            elem.append(clonedTemplate);

        });
    });