如何在AngularJS中实现控制器特征

时间:2014-02-10 18:39:32

标签: javascript angularjs

我想给一组控制器访问特征中定义的方法和属性。现在我提出的最好的实现是:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, CtrlTrait) {
  $scope.name = CtrlTrait.presetName;
  CtrlTrait.setGreeting.call($scope, 'Hello');
});

app.service('CtrlTrait', function() {
  this.setGreeting = function(greeting) { this.greeting = greeting; }
  this.presetName = 'tom';
});

Plunkr Code

这很好,但我希望通过控制器的$ scope可以访问这些属性和方法,而无需在每个控制器中手动创建别名。我希望能够通过将服务注入控制器来使用模板中的属性和方法。

这是可能的,还是我必须创建一个[包装] / [{1}} [{1}}的提供者,例如预设我想要的属性和方法的$scope

4 个答案:

答案 0 :(得分:6)

您可以尝试使用angular.extend这样的结果:angular.extend($scope,CtrlTrait);它允许我们在$scope中使用与您的服务相同的功能。所以,你可以直接在你的html中使用这个函数:

 <button ng-click="setGreeting('Good bye! ')">Good Bye</button>

以下是适合您的plunker演示:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, CtrlTrait) {
  $scope.name = CtrlTrait.presetName;
 // CtrlTrait.setGreeting.call($scope, 'Hello');
  angular.extend($scope,CtrlTrait);
  $scope.setGreeting('Hello World');
});

app.service('CtrlTrait', function() {
  this.setGreeting = function(greeting) { this.greeting = greeting; }
  this.presetName = 'tom';
});

http://plnkr.co/edit/BENS78mjFfpc6VCEtgK8?p=preview

答案 1 :(得分:1)

您可以在控制器中尝试以下内容

$scope.setGreeting = CtrlTrait.setGreeting

以后可以使用

$scope.setGreeting.call($scope, 'Hello');

评论后编辑

试试这个

  var app = angular.module('plunker', []);
  app.controller('MainCtrl', function($scope, CtrlTrait) {
    $scope.trait = CtrlTrait;
    $scope.name = $scope.trait.presetName;
    $scope.trait.setGreeting.call($scope,'Hello');
  });

  app.service('CtrlTrait', function() {
    var trait = {};
    trait.setGreeting = function(greeting) { this.greeting = greeting; }
    trait.presetName = 'tom';
    return trait;
  });

答案 2 :(得分:1)

所以我在前面加上免责声明...我会建议您实际执行此操作,或者至少不这样做。您可以在围绕模块化和注入构建的框架内添加控制器和服务之间的额外耦合,所有这些都是为了节省一些方法调用。

那就是说,这是实现你想要的方式的一种方式。 (JSFiddle here

var app = angular.module('myApp', []);

var controllerMaker = function(trait,controllerCode){
    return function($scope, $injector){

        //'apply' traits to this scope
        var apply = function(trait){
            trait.applyTo($scope);
        }
        apply.$inject = [trait];
        $injector.invoke(apply);

        //Finishes the other injections
        controllerCode.$inject = ['$scope'];
        controllerCode($scope);
    };
}

//Here's a sample 'trait'
app.service('CtrlTrait', function() {
    this.applyTo = function(obj){
        obj.setGreeting = function(greeting) { this.greeting = greeting; }
        obj.presetName = 'tom';
    }
});

//Then, setup your controller like this
app.controller('GreatController', controllerMaker("CtrlTrait",function($scope){ //Not using injection though!
    $scope.bleh = $scope.presetName; //will be 'tom'
}))

这有一定的弱点,比如你的控制器失去注射,但如果你真的想要,我相信你可以和$inject一起玩,找到适合你需要的东西。

答案 3 :(得分:1)

如果函数是对象,Angular将注入函数的返回值。所以在你的代码中:

var app = angular.module('plunker', []);

app.controller('MainCtrl',["$scope","DefaultName","TraitService", function($scope, defaultName, traitService) {
  $scope.name = defaultName;
  $scope.OKPressed = function() {
    traitService.setName($scope.name);
  };

});

// You can use .constant() for a constant value;

app.constant("DefaultName", "tom");

app.service('TraitService', function() {
  var traitService = {}; // The name does't matter
  traitService.setName = function(name) {
  // Not this.name = name because (this)is not guaranteed to persist or be the same across injections.
  // I am only using local storage to illustrate.  I usually use $rootScope to store 
  // Global variables. since they are always available on the $scope object without 
  // needing a service.
  // That might be a better way for you ($rootScope)
        localStorage.setItem("nameKey", name); 
  }
  traitService.getName = function () {
    return localStorage.getItem("nameKey");
  }
  return traitService; // This is what will be injected above
});