从控制器

时间:2015-10-09 13:01:43

标签: javascript angularjs angularjs-directive triggers controller

我有一个指令需要根据控制器中的服务调用结果进行一些DOM操作。以下是我目前正在遵循的方法:

1)在每个控制器范围内创建一个触发器对象,对应于视图中的每个指令 - 在需要时进行dom操作

2)创建指令并根据控制器设置的值进行dom操作;

app.directive("myDirective", function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            attrs.$observe('myDirective', function (value) {
                if (value === "true") {
                    $(element).text("Scrolled to####" + $(element).data("scroll"));
                }

            });
        }
    };
});

3)从相应的控制器方法将值设置为true以触发指令功能

app.controller("controller1", ["$scope", function ($scope) {
    $scope.trigger1 = false;

    $scope.triggerDirective1 = function () {

        $scope.trigger1 = true;
    };
    $scope.trigger2 = false;

    $scope.triggerDirective2 = function () {

        $scope.trigger2 = true;
    };
}]);

<div id="c1" ng-controller="controller1">Controller 1
    <br>List 1
    <div my-directive="{{trigger1}}" data-scroll="20"></div>List 2
    <div my-directive="{{trigger2}}" data-scroll="30"></div>
    <button ng-click="triggerDirective1()">Trigger Directive 1</button>
    <button ng-click="triggerDirective2()">Trigger Directive 2</button>
</div>

完整代码在此处 - http://jsfiddle.net/qec35dq4/

我发现这种方法不太好,原因如下:

1)附带指令的视图中会有多个元素

2)每个指令触发器都是独立的。任何时候只有一个指令可以运行。根据视图中的指令数量,我必须跟踪相应控制器中的所有触发器。

有没有更好的方法来解决这个问题,以便可以避免在控制器中跟踪这个触发器范围对象的依赖性?我想到了使用$broadcast/$emit,$on。但不要认为这也是一个很好的解决方案。请让我知道你的想法。

提前感谢您提供任何帮助

编辑:

新小提琴 - http://jsfiddle.net/86pk8LtL/

稍微改变了一下示例,以反映更多我想要实现的内容 - 页面上将有多个列表将应用此指令。基于后端的一些逻辑,需要选择一些项目列表。选择项目后,应滚动列表,以便第一个选定的项目在视图中(在示例中,我使用数据属性对滚动位置进行硬编码。但实际上指令会进行计算)。此指令的目的只是处理&#34;滚动查看&#34;部分这就是为什么我在保持范围属性方面有点怀疑。请注意,目前的方法工作正常。只是想看看是否有更好的方法。

4 个答案:

答案 0 :(得分:1)

AngularJS并不像使用事件驱动的库那样使用DOM查询。 我建议使用控制器提取。 由于Angular支持OOP标准,尝试嵌套控制器,子控制器的范围是从父控制器继承的,这意味着您可以观察触发哪个元素的状态。看看这个基本示例http://jsfiddle.net/qec35dq4/3/ 另外,我建议不要观察属性来将模型传递到指令的范围。这将帮助您避免观察属性更改。

最少但不是最后,你真的不需要注意元素的属性变化。它可以通过您的指令attrs获得:

app.directive("myDirective", function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            attrs.$observe('myDirective', function (value) {
                if (value === "true") {
                    $("#result").text(attrs.msg);
                }

            });
        }
    };
});

修改 这是基于您最新的JSFiddle的demo

答案 1 :(得分:0)

上周我不得不这样做。假设你不想写多个指令,交叉元素指令dom操作可能会很棘手,但是当我这样做时,我查找了ID所需的元素。这将使您不必在范围上定义方法。

<div id="trigger1"></div>List 2
<div id="trigger2"></div>
<button my-directive="trigger1" data-scroll="20">Trigger Directive 1</button>
<button my-directive="trigger2"  data-scroll="30">Trigger Directive 2</button>

指令。

app.directive("myDirective", function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
                var idElem = document.getElementById(attrs.myDirective);
                var elementToChange = angular.element(idElem);
                element.on("click", function(){
                    elementToChange.text("Scrolled to####" + attrs.dataScroll);
                });
            });
        }
    };
});

答案 2 :(得分:0)

看一下这个指令:https://github.com/iameugenejo/ngScrollTo 这似乎是一种非常巧妙的方式来实现你想要的。

答案 3 :(得分:0)

我想提两件事

  1. AngularJs与DOM操作无关。

  2. 指令的工作概念,它必须完全独立于控制器而且必须在所有地方工作。

  3. 在我看来,指令触发必须基于数据。

    因此,如果根据数据触发多指令,那么在单个视图中使用多指令会出现问题