AngularJS - an extension module with native types / providers

I want to add a new (dialog) type to angular, so I could use it the same way I use module.directive , module.filter , module.controller to register directives, filters, and controllers.

I want to register my dialog type instances as follows:

 module.dialog('prompt',function(dependencies){ return { templateUrl:'prompt.html', controller:function($scope){}, something:'value' } }); 

I also want to be able to use registered dialogs in controllers (dependency injection)

 module.controller('ListCtrl',function($scope,prompt){ $scope.deleteItem = function(item){ prompt('Do you want to delete this item?').then(function(result){ if(result) item.$delete(); }); } }); 

It comes down to the following questions:

  • How to extend angular module so module.dialog registers my dialog types?

  • How to make registered dialogs available to controllers , etc.

Btw,

  • I know about angular-ui and angular-strap .
  • I would prefer not to use dialog as a service, but as a separate type (this solution is already implemented in angular-ui ).
+8
angularjs angularjs-service
source share
1 answer

This is a rather interesting question. I will provide my answer with an opinion: I do not think you should extend angular.module to provide a dialog method. These methods are shortcuts to the built-in Angular providers, and the Angular team adds some commands from time to time. Since you can access the functionality you are looking for without adding the dialog method, I would not do that. However, the code below shows you how a very simple version can work (it does not modify the prototype of the Angular module, only one instance of the module).

 <div ng-app="myApp"> <div ng-controller='MainController'> <div> <button ng-click='askName()'>Ask Name</button> <button ng-click='askNameAgain()'>Ask Name Again</button> <button ng-click='askAge()'>Ask Age</button> <button ng-click='askFood()'>Ask Food</button> </div> <div>{{lastResponse}}</div> </div> </div> 
 var app = angular.module('myApp', []); // Provide some basic injectables for testing app.constant('nameString', 'NAME'); app.constant('ageString', 'AGE'); app.constant('foodString', 'FAVORITE FOOD'); // Create the dialog provider app.provider('dialog', function($provide, $injector) { var dialogs = {}; this.register = function(name, configFn) { // Create a new service $provide.factory(name, function($window, $q) { dialogs[name] = function() { // Get data based on DI injected version of configFn var data = $injector.invoke(configFn); // faking async here since prompt is really synchronous var deferred = $q.defer(); var response = $window.prompt(data.text); deferred.resolve(response); return deferred.promise; }; return dialogs[name]; }); }; // Injecting the service itself gives you a function that // allows you to access a dialog by name, much like $filter this.$get = function() { return function(name) { return dialogs[name]; }; }; }); // Providing dialog injectables via app.config app.config(function(dialogProvider) { dialogProvider.register('askFood', function(foodString) { return { text: 'What is your ' + foodString + '?' } }); }); // Alternatively, shortcut to accessing the dialogProvider via app.dialog app.dialog = function(name, configFn) { app.config(function(dialogProvider) { dialogProvider.register(name, configFn); }); }; app.dialog('askName', function(nameString) { return { text: 'What is your ' + nameString + '?' } }); app.dialog('askAge', function(ageString) { return { text: 'What is your ' + ageString + '?' } }); app.controller('MainController', function($scope, askName, askAge, askFood, dialog) { var setLastResponse = function(result) { $scope.lastResponse = result; }; $scope.askName = function() { askName().then(setLastResponse); }; $scope.askNameAgain = function() { // get the dialog through the dialog service // much like how $filter works var theDialog = dialog('askName'); theDialog().then(setLastResponse); }; $scope.askAge = function() { askAge().then(setLastResponse); }; $scope.askFood = function() { askFood().then(setLastResponse); }; }); 

Here is a working example: http://jsfiddle.net/BinaryMuse/zj4Jq/

Using $injector.invoke inside your dialogProvider.register function, you can provide the ability to use a key of type controller in the data returned by configFn . Since directive works just like it already does, you can get a lot from AngularJS source validation.

+7
source share

All Articles