【问题标题】:How to distinguish multiple directives in the same $scope?如何区分同一个 $scope 中的多个指令?
【发布时间】:2014-09-03 13:15:23
【问题描述】:

我实际上是从这样的控制器调用指令函数:

function myControllerFunction = function () {
    $scope.highlight();
}

highlight(),是指令中的一个函数。

如果我有两个不同的指令,每个指令都有自己的highlight() 函数怎么办?

有没有办法获取实际的指令object,而不是直接通过$scope访问指令函数?

我希望明确说明我想使用的指令,如下所示:

function myControllerFunction = function () {
    $scope.myDirective.highlight();
}

这可能吗?

如果你想知道为什么我想让控制器与指令对话,这里有一个例子:

我的控制器从用户那里收到一个身份验证密码并将其提交给服务。如果 pin 有效,则服务返回 true,否则返回 false。

在我的控制器函数中,我检查布尔返回值。如果是真的,我调用一个指令函数,叫做highlight,如果它是真的,它只是将一个div高亮为绿色,否则,我调用它以红色高亮它。

这是我的控制器功能:

$scope.keypadEnter = function () {
    userService.isCodeValid($scope.code).then(function (result)
    {
        if (JSON.parse(result.data)) {
            $scope.highlight("lime").then(function () {
                $scope.code = "";
                $location.path('/clockin');
            });
        }
        else
        {
            $scope.highlight("red").then(function () {
                $scope.resetDisplay();
                $scope.code = "";
            });
        }
    });
};

这是我的指令的高亮功能:

...
link: function ($scope, $element, $attrs) {
    $scope.highlight = function (color) {
        var deferred = $q.defer();

        $element.effect("highlight", { color: color }, 500);

        $element.find("span").css('color', '#000')
            .animate({ opacity: 0 }, 500, function () {
                $element.find("span").css('opacity', 1).css('color', '#fff')
            });

        $timeout(deferred.resolve, 500);

        return deferred.promise;
    }
...

根据您的建议,我已更改指令代码以监视 $scope.color 变量,如下所示:

angular.module('clockin').directive('grDisplay', function ($q, $timeout) {
    return {
        restrict: 'A',
        link: function ($scope, $element, $attrs) {

            $attrs.observe('color', function (color) {
                var deferred = $q.defer();

                $element.effect("highlight", { color: color }, 500);

                $element.find("span").css('color', '#000')
                    .animate({ opacity: 0 }, 500, function () {
                        $element.find("span").css('opacity', 1).css('color', '#fff')
                    });

                $timeout(deferred.resolve, 500);

                return deferred.promise;
            });
        }
    }
});

这是我的视图代码:

<div data-gr-display ng-attr-color="{{ color }}" class="display"><span>{{code}}</span></div>

但我收到此错误:

TypeError: object doesn't support this property or method « observe »
   at link (http://localhost:18000/App/clockin/keypad/display-directive.js:6:13)
   at nodeLinkFn (http://localhost:18000/Scripts/angular.js:6692:13)
...

【问题讨论】:

  • 与其从控制器显式调用函数,在每个指令的链接函数中显式定义作用域对象不是更容易混淆吗?即 $scope.highlightA = 等?然后调用 $scope.highlightA 或 B?
  • 这是个好主意。谢谢 !唯一的事情是,因为我已经阅读了下面 Adlen 的回答,我不确定我是否做对了(从控制器方法调用指令)。有没有更好的方法来完成这项工作?
  • 这通常是服务的工作,将它注入你的控制器并使用它的方法或数据对象,但如果这对你有用,我想没关系(直到它不是问题:P )
  • 我刚刚用一个可能的实现更新了我的答案,看看,让我知道它是否适合你。

标签: javascript angularjs angularjs-directive scope


【解决方案1】:

您的控制器必须从指令中调用方法似乎很奇怪。您能否提供更多信息说明您为什么这样做?

您似乎想让您的控制器和指令一起交谈。为此,这里有几个选项。

如果基于浏览器事件,您可以使用 docCreating a Directive that Adds Event Listeners 部分中描述的事件侦听器

您可以使用angular events 来广播事件。

最后你可能想在你的指令模板上调整一个参数,说它是高亮的。

根据问题编辑:

如果您只需要更改 CSS,您可以在指令中使用 ng-class 属性,如下所示:

<my-directive ng-class="{{ status }}"></my-directive>

使用属性,您可以执行以下操作:

link: function ($scope, $element, $attrs) {
    $attrs.$observe('color', function(color)){
        var deferred = $q.defer();

        $element.effect("highlight", { color: color }, 500);

        $element.find("span").css('color', '#000')
            .animate({ opacity: 0 }, 500, function () {
                $element.find("span").css('opacity', 1).css('color', '#fff')
            });

        $timeout(deferred.resolve, 500);

        return deferred.promise;
}

在你看来:

<my-directive ng-attr-color="{{ color }}"></my-directive>

或者如果你想要一个通知系统,你可以参考Angular UI Bootstrap alert (但我仍然不明白为什么你需要几个指令来解决你的问题)

【讨论】:

  • 我已经编辑了我的问题来解释我为什么要这样做。谢谢。
  • 你是对的。对于我的问题,我不需要多个指令。我只是对控制器 --> 指令通信感到困惑,以防我最终会在同一范围内处理多个指令。要回答您的最后评论,我不确定这是否只是 CSS 更改:我使用 jquery-ui 的 highlight 方法。这对 ng-class 可行吗?
  • 不确定是否只对 jquery ui 使用 CSS,但我为您提供了一个基于属性的示例
  • 对不起。我不知道 ng-attr。 ng-attr-color 来自哪里?这是您为属性指定的自定义名称吗?实际上,这是我要突出显示的背景颜色。我也让前景色淡出。
  • 这只是一种避免浏览器拒绝某些属性的方法。在此处查看角度文档(ngAttr attribute bindings 部分)docs.angularjs.org/guide/directive
【解决方案2】:

通常您与指令通信的方式是通过属性,您通常不会在指令级别在控制器范围内定义方法。

我相信,在您的情况下,正确的方法是在指令中使用绑定到范围属性的属性,并且您的指令会监视该属性,因此当它发生更改时,它会运行特定的函数。

一个可能的实现可能是:

控制器:

$scope.onHightlight = function() {
   if ($scope.highlightColor === 'lime') {
       scope.code = "";
       $location.path('/clockin');
   } else {
       $scope.resetDisplay();
       $scope.code = "";
   }
});
$scope.keypadEnter = function () {
    userService.isCodeValid($scope.code).then(function (result) {
        if (JSON.parse(result.data)) {
            $scope.highlightColor = "lime";
        }
        else {
            $scope.highlightColor = "red";
        }
    });
};

指令:

link: function ($scope, $element, $attrs) {
    var onHightlight = $scope.$eval($attrs['onHightlight']);

    $scope.$watch($attrs['hightlight'], function(color) {

        $element.effect("highlight", { color: color }, 500);

        $element.find("span").css('color', '#000')
            .animate({ opacity: 0 }, 500, function () {
                $element.find("span").css('opacity', 1).css('color', '#fff')
            });

        $timeout(onHightlight, 500);
    }
 ....
}

HTML:

<your-directive highlight="highlightColor" onHighlight="onHightlight"></your-directive>

【讨论】:

  • 谢谢。您能否根据我为指令提供的代码提供一个示例?
  • 非常感谢您抽出宝贵的时间。有一个指令监视范围是要走的路。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-05
  • 1970-01-01
  • 2015-09-17
  • 1970-01-01
  • 2016-10-20
  • 1970-01-01
相关资源
最近更新 更多