【问题标题】:AngularJS - extending module with own types / providersAngularJS - 使用自己的类型/提供者扩展模块
【发布时间】:2013-04-28 09:32:24
【问题描述】:

我想为 angular 添加一个新的(对话框)type,这样我就可以像使用 module.directivemodule.filtermodule.controller 一样使用它来注册指令、过滤器和控制器。

我想以这种方式注册dialog 类型的实例:

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

我还希望能够在控制器中使用已注册的对话框(依赖注入)

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();
        });
    }
});

归结为以下问题:

  1. 如何扩展 Angular 的模块以让 module.dialog 注册我的 dialog 类型?

  2. 如何使我注册的dialogs 可注入controllers 等?

顺便说一句,

  • 我知道angular-uiangular-strap
  • 我宁愿不将dialog 用作服务,而是将type 用作单独的type(此解决方案已在angular-ui 中实现)。

【问题讨论】:

  • 你为什么不直接使用指令?
  • 与引导解决方案相比,您是否有理由这样做?
  • @zcaudate,我不喜欢引导程序注册对话框的方式——你在控制器中定义你的对话框。我想将对话框与控制器分开。

标签: angularjs angularjs-service


【解决方案1】:

这是一个非常有趣的问题。我会在回答前加上一个意见:我认为您不应该扩展 angular.module 来提供 dialog 方法。这些方法是内置 Angular 提供程序的快捷方式,Angular 团队会不时添加一些方法。因为您可以访问您正在寻找的功能 添加dialog 方法,我不会。也就是说,下面的代码确实向您展示了一个非常基本的版本是如何工作的(它不会修改 Angular 模块原型,只是模块的单个实例)。

<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);
  };
});

这是一个工作示例:http://jsfiddle.net/BinaryMuse/zj4Jq/

通过在dialogProvider.register 函数内部利用$injector.invoke,您可以提供在configFn 返回的数据中使用controller 之类的键的能力。由于directive 已经有很多类似的工作方式,您可能会从查看the AngularJS source 中获益良多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-30
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-15
    相关资源
    最近更新 更多