Home:ALL Converter>How to expose directive methods using a service

How to expose directive methods using a service

Ask Time:2017-07-19T04:36:51         Author:saulsluz

Json Formatter

How to expose directive methods without using $broadcast or '=' between modules?

Using $broadcast (events) if there are multiple directives all will be notified. It cannot return value too.

Exposing directive's function by html attribute I think it is not that best that Angular has to offer.

Angular Bootstrap UI do it using services (I guess): It have a service named "$uibModal". You can call a function "$uibModal.open()" of Modal Directive by injecting $uibModal service.

Is that the right way?

Author:saulsluz,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/45176602/how-to-expose-directive-methods-using-a-service
georgeawg :

An example of a directive that registers its API with a service:\n\napp.service(\"apiService\", function() {\n var apiHash = {};\n this.addApi = function (name,api) {\n apiHash[name] = api;\n };\n this.removeApi = function (name) {\n delete apiHash[name];\n };\n this.getApi = function (name) {\n return apiHash[name];\n };\n});\n\napp.directive(\"myDirective\", function (apiService) {\n return {\n restrict: 'E',\n scope: {},\n template: `<h1>{{title}}</h1>`,\n link: postLink\n };\n function postLink(scope, elem, attrs)\n var name = attrs.name || 'myDirective';\n var api = {};\n api.setTitle = function(value) {\n scope.title = value;\n };\n apiService.addApi(name, api);\n scope.$on(\"$destroy\", function() {\n apiService.removeApi(name);\n });\n }\n});\n\n\nElsewhere in the app, the title of the directive can be set with:\n\napiService.getApi('myDirective').setTitle(\"New Title\");\n\n\nNotice that the directive registers the api with a name determined by the name attribute of the directive. To avoid memory leaks, it unregisters itself when the scope is destroyed.\n\n\n\nUpdate\n\n\n How could I use it from a controller? \n\n\n app.controller('home', function($scope,apiService) {\n $scope.title = \"New Title\";\n $scope.setTitle = function() {\n apiService.getApi('mainTitle').setTitle($scope.title);\n };\n })\n\n\n\n\n <body ng-controller=\"home\">\n\n <my-directive name=\"mainTitle\"></my-directive>\n <p>\n <input ng-model=\"title\" />\n <button ng-click=\"setTitle()\">Set Title\n </button>\n </p>\n </body>\n\n\nThe DEMO\n\n\r\n\r\nangular.module('myApp', [])\r\n .service(\"apiService\", function() {\r\n var apiHash = {};\r\n this.addApi = function(name, api) {\r\n apiHash[name] = api;\r\n };\r\n this.getApi = function(name) {\r\n return apiHash[name];\r\n };\r\n })\r\n\r\n.directive(\"myDirective\", function(apiService) {\r\n return {\r\n restrict: 'E',\r\n scope: {},\r\n template: `<h1>{{title}}</h1>`,\r\n link: postLink\r\n };\r\n\r\n function postLink(scope, elem, attrs) {\r\n var name = attrs.name || 'myDirective';\r\n var api = {};\r\n api.setTitle = function(value) {\r\n scope.title = value;\r\n };\r\n apiService.addApi(name, api);\r\n scope.$on(\"$destroy\", function() {\r\n apiService.addApi(name, null);\r\n });\r\n }\r\n })\r\n \r\n .controller('home', function($scope,apiService) {\r\n $scope.title = \"New Title\";\r\n $scope.setTitle = function() {\r\n apiService.getApi('mainTitle').setTitle($scope.title);\r\n };\r\n })\r\n<script src=\"//unpkg.com/angular/angular.js\"></script>\r\n<body ng-app=\"myApp\" ng-controller=\"home\">\r\n \r\n <my-directive name=\"mainTitle\"></my-directive>\r\n <p>\r\n <input ng-model=\"title\" />\r\n <button ng-click=\"setTitle()\">Set Title\r\n </button>\r\n </p>\r\n </body>",
2017-07-18T22:03:54
Jarek Kulikowski :

.factory('myService', [function() {\n return {\n charCount: function(inputString) {\n return inputString.length;\n }\n }\n}])\n\n\nthis service exposes function charCount();\nin your directive you have to inject it like this\n\n.directive('testDirective', ['myService', function(myService) {\n return {\n restrict: 'A',\n replace: true,\n template: \"<div>'{{myTestString}}' has length {{strLen}}</div>\",\n link: function($scope, el, attrs) {\n $scope.myTestString = 'string of length 19';\n $scope.strLen = myService.charCount( $scope.myTestString );\n }\n }\n}])\n\n\nand, of course call it \n\n$scope.strLen = myService.charCount( $scope.myTestString );\n",
2017-07-18T20:40:00
yy