0

我正在尝试在数据表中设置一个简单的突出显示机制:

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Owner</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="file in files" highlightable> <!-- Multiple instances of highlightable -->
            <td>{{file.name}}</td>
            <td>{{file.owner}}</td>
        </tr>
    </tbody>
</table>

我有一个处理突出显示的指令。您单击 ,<tr>它将尝试首先取消突出显示所有其他<tr>,然后突出显示单击的那个。

directive('highlightable', function() {
    return {
        require: 'highlightable',
        controller: function($scope, $element) {
            this.unhighlight = function(file) {
                $element[0].style.backgroundColor = 'transparent';
            };
        },
        link: function(scope, element, attrs, ctrl) {
            var color = '#DEE4FC';
            element.bind('click', function(e) {
                ctrl.unhighlight(scope.file);
                element[0].style.backgroundColor = color;
            });
        }
    };
});

问题是它似乎并没有访问指令控制器的每个实例。当需要另一个指令时,如何确保我在ng-repeat场景中需要该指令的每个实例,并通过每个重复指令的控制器方法操作每个实例?

http://jsfiddle.net/txBJ6/1/

4

3 回答 3

1

鉴于您要实现的目标,我会这样做。基本上使用范围通知在元素之间进行通信。

directive('highlightable', function() {
    return {
        link: function(scope, element, attrs) {
            var color = '#DEE4FC';
            scope.$on("reset", function() {
                element[0].style.backgroundColor = 'transparent';
            });
            element.bind('click', function(e) {
                scope.$parent.$broadcast("reset");
                element[0].style.backgroundColor = color;
            });
        }
    };
});

演示:链接

更新
的 sze 正确地指出,我的解决方案仅适用于您只需要一个列表(您的问题似乎就是这种情况)。但是,在保持代码简洁的同时容纳多个列表非常容易。

<tr ng-repeat="file in files" highlightable="list1">
    <td>{{file.name}}</td>
    <td>{{file.owner}}</td>
</tr>

...

<tr ng-repeat="file in files" highlightable="list2">
    <td>{{file.name}}</td>
    <td>{{file.owner}}</td>
</tr>

...

directive('highlightable', function () {
    return {
        link: function (scope, element, attrs) {
            var color = '#DEE4FC';
            scope.$on(attrs.highlightable, function () {
                element[0].style.backgroundColor = 'transparent';
            });
            element.bind('click', function (e) {
                scope.$parent.$broadcast(attrs.highlightable);
                element[0].style.backgroundColor = color;
            });
        }
    };
});

演示:链接

于 2013-08-29T22:18:50.870 回答
1

[@buu Nyuyen] 的问题是他错过了一些处理范围的逻辑。如果你有另一个被指令修改的highlightable列表,如果事件从第一个列表广播,第二个列表将受到影响,并使指令不可重用。你可以在这里看到这个问题。Issue

但是,您可以通过循环其他元素轻松实现它。诀窍是您可以使用element[0].parentElement.children.

directive('highlightable', function () {
    return {
        require: 'highlightable',
        controller: function ($scope, $element) {
            this.unhighlight = function (element) {
                element.style.backgroundColor = 'transparent';
            };
        },
        link: function (scope, element, attrs, ctrl) {
            var color = '#DEE4FC';
            element.bind('click', function (e) {
                angular.forEach(element[0].parentElement.children, function (element) {
                    ctrl.unhighlight(element);
                })
                element[0].style.backgroundColor = color;
            });
        }
    };
});

Working Demo

于 2013-08-30T00:34:03.343 回答
0

最简单的解决方案是 Buu Nguyen 提出的解决方案,我提供了一个更困难的解决方案。

解决此问题的典型方法之一是拥有一个了解每个孩子的父指令。因此,您可以在那里注册每一行,当您单击一个时,父级将取消突出显示其他子级。

更复杂但更可配置。您可以创建一个名为... 的属性multi,以便能够突出显示多个。甚至可以选择最多x行......你想要什么。

如果你好奇,我把演示留在这里:http: //jsfiddle.net/5NSW3/1/

于 2013-08-29T22:29:35.197 回答