如何从孤立范围指令揭露的行为呢?(How to expose behavior from a dir

2019-08-21 11:57发布

我如何可以公开从指令的方法? 我知道,我应该使用的属性数据,但我真的想揭露的行为 ,而不是数据 。 东西父控制器可以调用。

比方说,我的DOM的样子:

<div ng-app="main">
    <div ng-controller="MyCtrl">
        <button ng-click="call()" >Call</button>
        <div id="container" my-directive> </div>
    </div>
</div>

JavaScript的:

angular.module("main", []).controller("MyCtrl", function($scope) {
    $scope.call = function() {
        $scope.myfn();
    };
}).directive("myDirective", function() {
    return {
        // scope: {},
        controller: function($scope) {
            $scope.myfn = function() {
                console.log("myfn called");
            }
        }
    };
});

的jsfiddle: http://jsfiddle.net/5gDjQ/7/

如果scope被注释掉(即指令不具有隔离范围),它工作得很好。 当我按下按钮, myfn被称为和日志控制台。

只要我去掉scope ,这是行不通的。 myfn是指对儿童的范围和不会轻易提供给家长。

在我来说,我认为污染父范围是一个坏主意,我真的想避免它。

所以,我怎么可以公开从指令父控制器的功能? 或者:我怎样才能调用从父控制器指令的方法?

Answer 1:

可以用分离的范围由设置在这绑定到控制器双向范围的变量(使用“=”)执行此操作。 在你的指令,你可以在函数然后分配给该变量,角将使用绑定找到您的控制器对应的变量。 该变量将指向您的控制器可以调用一个函数。

http://jsfiddle.net/GWCCr/

HTML:注意新ATTRIB:

<div ng-app="main">
    <div ng-controller="MyCtrl">
        <button ng-click="call()" >Call</button>
        <div id="container" my-directive my-fn="fnInCtrl"> </div>
    </div>
</div>

JS:

angular.module("main", []).controller("MyCtrl", function($scope) {
    $scope.call = function() {
        $scope.fnInCtrl();
    };
}).directive("myDirective", function() {
    return {
        scope: {
            myFn: '='
        },
        controller: function($scope) {
            $scope.myFn = function() {
                console.log("myfn called");
            }
        }
    };
});


Answer 2:

而不是试图找出如何调用隐藏的指令,我觉得里面的函数,你应该问自己: 为什么我要调用的指令定义的功能?

其中一个原因,我能想到的是:触发也可以通过应用程序的用户从指令中触发该指令的一些行为

如果是这样,显然和Angulary的事情将播出包含应该对其做出反应的指令一个范围的事件 。 然后,该指令会听取该事件,并通过自身触发其功能。

这有额外的好处:

  • 您可以在事件数据对象发送参数,如果你想
  • (如果它们形成集合例如),您可以触发多个指令的反应
  • 可以用一个指令,该指令是在该范围层次深通信(例如,如果该指令是另一指令,是其他指令的内部,等等内),而不传递函数回调通过每个嵌套指令
  • 它不会破坏该指令的隔离

让我们试着想出了一个很简单的例子:假设我们有一个显示从某处下载随机励志报价的Widget。 它也有一个按钮,涨跌幅为不同的一种。

下面是该指令的模板:

<p>{{ quote }}</p>
<button ng-click="refreshQuote()"></button>

而这里的指令的代码:

app.directive("randomQuote", function () {
  return {
    restrict: "E",
    scope: {},
    link: function (scope) {
      scope.refreshQuote = function () {
        scope.quote = ... // some complicated code here
      };
      scope.refreshQuote();
    }
  };
});

请注意,该指令是完全独立的:它有一个分离的范围和它本身并不报价取。

让我们假设,我们也希望能够从控制器刷新报价。 这可能是因为在控制器代码中调用这个简单:

$scope.$broadcast("refresh-random-quote");

要添加事件处理程序,我们必须将此代码添加到link指令的功能:

scope.$on("refresh-random-quote", function () {
  scope.refreshQuote();
});

通过这种方式,我们创建了从控制器到该指令的单向通信信道不破该指令的隔离,同时工作,如果该指令代码的范围层次广播事件嵌套深。



Answer 3:

我怎样才能从暴露指令父控制器的功能?
或者:我怎样才能调用从父控制器指令的方法?

嗯,我不认为你应该尝试做到这一点(即耦合控制器行为的指令),但如果你必须...这里有一个方法可以做到这一点:通过一个控制器功能到你的指令,其中,指令可以打电话通知指示功能的控制器:

<div id="container" my-directive cb="setDirectiveFn(fn)"></div>

directive("myDirective", function() {
    return {
       scope: { cb: '&' },
        controller: function($scope) {
            $scope.myfn = function() {
                console.log("myfn called");
            }
            $scope.cb({fn: $scope.myfn});
        }
    };
});

小提琴



Answer 4:

为了contribuite,@georgeawg给我用服务做的工作凉爽的解决方案。 这样,您就可以处理同一个页面上的多个指令。

<html ng-app="myApp">
<head>
  <script src="https://opensource.keycdn.com/angularjs/1.6.5/angular.min.js"></script>
</head>
<body ng-controller="mainCtrl">
  <h1>^v1.6.0 ($postLink hook required)</h1>
  <my-directive name="sample1" number="number1"></my-directive>
  <my-directive name="sample2" number="number2"></my-directive>
</body>
<script>
  angular.module('myApp', [])
    .controller('mainCtrl', ['$scope', 'myDirectiveFactory', function ($scope, myDirectiveFactory) {
      $scope.number1 = 10
      $scope.number2 = 0
      this.$postLink = function () {
        myDirectiveFactory.get('sample2')
          .increment()
          .increment()
          .increment()
          .increment()
        myDirectiveFactory.get('sample1')
          .increment()
          .increment()
        myDirectiveFactory.get('sample2')
        .decrement()
      }
    }])
    .factory('myDirectiveFactory', function () {
      var instance = {}
      return {
        get: function (name) {
          return instance[name]
        },
        register: function (name, value) {
          return instance[name] = value
        },
        destroy: function (name) {
          delete instance[name]
        }
      }
    })
    .controller('myDirectiveCtrl', ['$scope', 'myDirectiveFactory', function ($scope, myDirectiveFactory) {
      $scope.name = $scope.name || 'myDirective'
      $scope.$on('$destroy', function () {
        myDirectiveFactory.destroy($scope.name)
      })
      var service = {
        increment: function () {
          $scope.number++
          return this
        },
        decrement: function () {
          $scope.number--
          return this
        }
      }
      myDirectiveFactory.register($scope.name, service)
    }])
    .directive('myDirective', [function () {
      return {
        controller: 'myDirectiveCtrl',
        restrict: 'E',
        scope: {
          number: '<',
          name: '@?'
        },
        template: '<p> {{ number }} </p>'
      }
    }])
</script>
</html>


Answer 5:

AngularJS V1.7.1的版本*引入了新的NG-REF指令 。

的NG-REF属性告诉AngularJS发布一个组件的控制器上的当前范围。 这对于具有一个成分是有用的,诸如音频播放器暴露其API来同级组件。 它的播放和停止控件可以很容易地访问。

欲了解更多信息,请参阅

  • AngularJS ng-ref指令API参考
  • 新AngularJS NG-REF指令的陷阱 。


文章来源: How to expose behavior from a directive with isolated scope?