如何覆盖angular.js插件中的控制器函数

时间:2014-05-21 15:43:28

标签: javascript angularjs angularjs-directive angularjs-controller

在开发我的第一个Angular.js项目的同时,我遇到了麻烦。经过一天的研究,我不知道如何覆盖插件控制器方法。

我正在使用一个非常好的https://github.com/ManifestWebDesign/angular-gridster插件,但是一些控制器功能(例如GridsterCtrl.updateHeight)并不适合我的任务。

请记住编辑插件代码是一个坏主意(因为我想使用http://bower.io/保持Gridster最新),我知道Gridster控制器函数需要在其他地方重写。

在这种情况下,似乎指令没有帮助,那么如何完成覆盖 - 或者我在这里面临完全错误的方向?

感谢您的时间。

1 个答案:

答案 0 :(得分:1)

根本不想做什么,但我建议继承控制器并覆盖你需要的东西。我喜欢this blog

中解释的两种不同方法

对于这个答案的长寿,我正在复制一些摘录。

在AngularJS中,通过$ injector服务在任何点请求任何已定义的依赖关系是微不足道的。这很容易被滥用,会让你以后的生活变得困难,但它也有其用途。以下是我们如何使用它来将控制器安排到继承层次结构中,从通用父控制器的定义开始:

function ParentController($scope, myService) {
  // In this form of inheritance, properties are set in reverse order: child sets 
  // first, then parent. So a property that is intended to be overridden has to
  // check for its own existence.
  //
  // e.g. Only create this function if it hasn't already been set by the child.
  this.decorateScope = this.decorateScope || function () {
    $scope.decorator = myService.getDecorator() + 2;
  }

  // Setting up an initialize function is another necessary part of enabling child
  // controllers to override features of the parent. All setup is delayed to the
  // end of instantiation, allowing individual functions and properties to be 
  // overridden first.
  this.initialize = this.initialize || function () {
    this.decorateScope();
  }

  // This will be invoked last of all when a child controller is instantiated.
  initialize();
}

接下来,我们定义一个继承自上面父代的子控制器:

function ChildController($injector, $scope, myService) {
  // Override the parent function while still allowing further children to override
  // it.
  this.decorateScope = this.decorateScope || function () {
    $scope.decorator = 44;
  }

  // This is the magic by which this controller inherits from the ParentController.
  // Essentially the ParentController function is invoked on "this" and is passed
  // dependencies directly.
  // 
  // Note that this means a child controller must have all of the dependencies
  // required by the parent.
  $injector.invoke(ParentController, this, {
    $scope: $scope,
    myService: myService
  });
}

实际上可以跳过将除$ scope之外的任何依赖项从子控制器传递到父控制器。一切都会有效,直到你开始编写测试代码,在这些代码中你注入了模拟依赖项。任何未显式传递到$ injector.invoke()的依赖项都将被实例化为真实的,而不是测试用例中指定的模拟。这显然非常不方便,并且会完全破坏您的测试 - 所以总是明确地传递所有依赖项。

这种继承方法支持方便的mixin,因为mixin的工作方式与继承完全相同:

function ChildController($injector, $scope, myService, otherService) {
  // Any number of controllers can be invoked in this way. They will apply
  // their properties and overrides in the order they are invoked. So if you
  // want a mixin to override the parent, it has to come first.
  $injector.invoke(MixinController, this, {
    $scope: $scope,
    otherService: otherService
  });
  $injector.invoke(ParentController, this, {
    $scope: $scope,
    myService: myService
  });
}