5

В моем приложении у меня есть два почти одинаковых контроллера. Множество функций одно и то же, поэтому я хотел бы прототипировать их. Это контроллер # 1:Как сделать прототип из 2 идентичных контроллеров в угловых?

c2gcontroller.js

angular.module('c2gyoApp') 
    .controller('C2gCtrl', function($scope) { 
    // some unique stuff 
    $scope.feeDay = 59; 
    ... 
    // the identical functions 
    $scope.getMinutes = function(minutes) { 
     var duration = moment.duration(minutes, 'm'); 
     return duration.minutes(); 
    }; 
    ... 
    }); 

и контроллер # 2:

c2gbcontroller.js

angular.module('c2gyoApp') 
    .controller('C2gbCtrl', function($scope) { 
    // some unique stuff 
    $scope.feeDay = 89; 
    ... 
    // the identical functions 
    $scope.getMinutes = function(minutes) { 
     var duration = moment.duration(minutes, 'm'); 
     return duration.minutes(); 
    }; 
    ... 
    }); 

Я попытался положить $scope.getMinutes в завод:

smfactory.js

angular.module('c2gyoApp') 
    .factory('smfactory', function() { 
    return { 
     getHours: function(minutes) { 
     var duration = moment.duration(minutes, 'm'); 
     return Math.ceil(duration.asHours() % 24); 
     } 
    }; 
    }); 

Я впрыскивается smfactory в c2gcontroller.js

c2gcontroller.js (попытка # 1)

angular.module('c2gyoApp') 
    .controller('C2gCtrl', function($scope, smfactory) { 
    ... 
    // the identical functions 
    $scope.getHours = smfactory.getHours(minutes); 
    ... 
    }); 

Это дает ошибку, минут не определено

line 33 col 42 'minutes' is not defined. 

Так что я пробовал:

c2gcontroller.js (попытка # 2)

angular.module('c2gyoApp') 
    .controller('C2gCtrl', function($scope, smfactory) { 
    ... 
    // the identical functions 
    $scope.getMinutes = function(minutes) { 
     return smfactory.getHours(minutes); 
    }; 
    ... 
    }); 

, который не дает ошибку, но мое приложение и не стал отвечать на запросы. В принципе $scope.getMinutes ничего не возвращает.

Я читал и смотрел много о услугах AngularJS, фабриках, поставщиках, но я не знаю, куда идти отсюда. Каким будет правильный способ прототипа c2gcontroller.js и c2gbcontroller.js?

ответ

2

Как насчет псевдо наследования с angular.extend

/* define a "base" controller with shared functionality */ 
.controller('baseCtrl', ['$scope', .. 
    function($scope, ...) { 

    $scope.getMinutes = function(minutes) { 
    var duration = moment.duration(minutes, 'm'); 
    return duration.minutes(); 
    }; 


.controller('C2gCtrl', ['$controller', '$scope', ... 
    function($controller, $scope, ...) { 

    // copies the functionality from baseCtrl to this controller 
    angular.extend(this, $controller('baseCtrl', {$scope: $scope})); 

    // some unique stuff 
    $scope.feeDay = 59; 

}) 

.controller('C2gbCtrl', ['$controller', '$scope', ... 
    function($controller, $scope, ...) { 

    // copies the functionality from baseCtrl to this controller 
    angular.extend(this, $controller('baseCtrl', {$scope: $scope})) 

    // some unique stuff 
    $scope.feeDay = 89; 
}) 
3

В этом месте, используя комбинацию JavaScript благоговения и синтаксис controller as действительно пригодится.

Если мы тянем свои общие функции из в обычный старый объект:

var commonStuff = { 
    getHours: function(minutes) { 
     var duration = moment.duration(minutes, 'm'); 
     return Math.ceil(duration.asHours() % 24); 
    } 
}; 

Тогда, если мы реорганизовать наш контроллер будет нормальный объект JS, мы можем увеличить его с Mixin одним из двух способов. Либо непосредственно на сам объект, либо через прототип.

//Using the instance 
function MyCtrl(){ 
    var vm = this; 

    angular.extend(vm, commonStuff); 

    //Other stuff 
} 

//Or via the prototype 
function MyCtrl(){ 
    var vm = this; 
} 

//Controller specific 
MyCtrl.prototype = { 

}; 

angular.extend(MyCtrl.prototype, commonStuff); 

Самая большая разница в том, что теперь вы можете просто ссылаться на контроллер непосредственно через использование синтаксиса controller as.

<div ng-controller="myCtrl as ctrl"> 
    <a href="" ng-click="ctrl.getHours(120)">Get Hours</a> 
</div> 
+0

Большое спасибо за ваш глубокий ответ!Я решил пойти с ответом user2264997, поскольку он не нарушает схему именования Yeoman. – mles