如何使用服务公开指令方法

时间:2017-07-18 20:36:52

标签: angularjs angularjs-directive angularjs-service

如何在不使用$ broadcast或' ='的情况下公开指令方法模块之间?

如果有多个指令,则使用$broadcast(事件)将通知所有指令。它也不能回报价值。

公开指令的功能by html attribute我认为Angular不是最好的。

Angular Bootstrap UI使用服务(我猜):它有一个名为" $ uibModal"的服务。 你可以调用一个函数" $ uibModal.open()"注入$ uibModal服务的Modal Directive。

这是正确的方法吗?

3 个答案:

答案 0 :(得分:1)

使用服务注册其API的指令示例:

app.service("apiService", function() {
    var apiHash = {};
    this.addApi = function (name,api) {
        apiHash[name] = api;
    };
    this.removeApi = function (name) {
        delete apiHash[name];
    };
    this.getApi = function (name) {
        return apiHash[name];
    };
});

app.directive("myDirective", function (apiService) {
    return {
        restrict: 'E',
        scope: {},
        template: `<h1>{{title}}</h1>`,
        link: postLink
    };
    function postLink(scope, elem, attrs)
        var name = attrs.name || 'myDirective';
        var api = {};
        api.setTitle = function(value) {
            scope.title = value;
        };
        apiService.addApi(name, api);
        scope.$on("$destroy", function() {
            apiService.removeApi(name);
        });
    }
});

在应用程序的其他地方,可以使用以下命令设置指令的标题:

apiService.getApi('myDirective').setTitle("New Title");

请注意,该指令使用由指令的name属性确定的名称来注册api。为了避免内存泄漏,它会在范围被破坏时取消注册。

更新

  

我如何在控制器中使用它?

  app.controller('home', function($scope,apiService) {
    $scope.title = "New Title";
    $scope.setTitle = function() {
      apiService.getApi('mainTitle').setTitle($scope.title);
    };
  })
  <body ng-controller="home">

    <my-directive name="mainTitle"></my-directive>
    <p>
      <input ng-model="title" />
      <button ng-click="setTitle()">Set Title
      </button>
    </p>
  </body>

The DEMO

angular.module('myApp', [])
  .service("apiService", function() {
    var apiHash = {};
    this.addApi = function(name, api) {
      apiHash[name] = api;
    };
    this.getApi = function(name) {
      return apiHash[name];
    };
  })

.directive("myDirective", function(apiService) {
    return {
      restrict: 'E',
      scope: {},
      template: `<h1>{{title}}</h1>`,
      link: postLink
    };

    function postLink(scope, elem, attrs) {
      var name = attrs.name || 'myDirective';
      var api = {};
      api.setTitle = function(value) {
        scope.title = value;
      };
      apiService.addApi(name, api);
      scope.$on("$destroy", function() {
        apiService.addApi(name, null);
      });
    }
  })
  
  .controller('home', function($scope,apiService) {
    $scope.title = "New Title";
    $scope.setTitle = function() {
      apiService.getApi('mainTitle').setTitle($scope.title);
    };
  })
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="myApp" ng-controller="home">
    
    <my-directive name="mainTitle"></my-directive>
    <p>
      <input ng-model="title" />
      <button ng-click="setTitle()">Set Title
      </button>
    </p>
  </body>

答案 1 :(得分:0)

.factory('myService', [function() {
    return {
        charCount: function(inputString) {
            return inputString.length;
        }
    }
}])

此服务公开函数charCount(); 在你的指令中,你必须像这样注入它

.directive('testDirective', ['myService', function(myService) {
    return {
        restrict: 'A',
        replace: true,
        template: "<div>'{{myTestString}}' has length {{strLen}}</div>",
        link: function($scope, el, attrs) {
            $scope.myTestString = 'string of length 19';
            $scope.strLen       = myService.charCount( $scope.myTestString );
        }
    }
}])

,当然叫它

$scope.strLen       = myService.charCount( $scope.myTestString );

答案 2 :(得分:0)

&#13;
&#13;
<html>
    <style>
        #out {
            width:96%;
            height:25%;
            padding:10px;
            border:3px dashed blue;
            font-family: monospace;
            font-size: 15px;
        }
    </style>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>

    <script>
        var APP = angular.module('MYAPP', []);

        APP.controller('main', ['$scope', '$element', '$compile', 'myService', function($scope, $element, $compile, myService) {
            $scope.test          = 'my Test Controller';
            $scope.directiveTest = "directive test";
            var testSvc = myService.charCount($scope.test);
            $scope.showTestDir = true;
        }])
        .directive('testDirective', ['myService', function(myService) {
            return {
                restrict: 'A',
                replace: true,
                template: "<div>'{{myTestString}}' has length {{strLen}}</div>",
                link: function($scope, el, attrs) {
                    $scope.myTestString = 'string of length 19';
                    $scope.strLen       = myService.charCount( $scope.myTestString );
                }
            }
        }])
        .factory('myService', [function() {
            return {
                charCount: function(inputString) {
                    return inputString.length;
                }
            }
        }])
        .filter('toUpper', function() {
            return function(input) {
                return input.toUpperCase();
            }
        })
        .filter('toLower', function() {
            return function(input) {
                return input.toLowerCase();
            }
        })
        ;
    </script>
        <body ng-app="MYAPP">
        <div id="out" ng-controller="main">
            {{test}} - not filtered
            <br/>
            {{test|toUpper}} - filtered toUpper
            <br/>
            {{test|toLower}} - filtered toLower
            <br/>
            <br/>
            <div test-directive ng-if="showTestDir"></div>
        </div>
    </body>
</html>
&#13;
&#13;
&#13;