5

In meiner Anwendung habe ich 2 fast identischen Controller. Viele Funktionen sind gleich, daher möchte ich sie als Prototypen verwenden. Dies ist Controller # 1:Wie erstellt man einen Prototyp aus 2 identischen Controllern in angularjs?

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

und Controller # 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(); 
    }; 
    ... 
    }); 

Ich habe versucht Putting $scope.getMinutes in eine Fabrik:

smfactory.js

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

I smfactory in c2gcontroller.js

c2gcontroller.js (Versuch # 1)

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

Dies ergibt einen Fehler haben, die injizierten Minuten nicht

definiert So

Ich habe versucht:

c2gcontroller.js (Versuch # 2)

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

, die keinen Fehler ergeben, aber meine App hat nicht mehr reagiert. Grundsätzlich $scope.getMinutes gibt jetzt nichts zurück.

Ich habe viel über AngularJS Dienstleistungen lesen und beobachtete, Fabriken, Provider, aber ich weiß nicht, wo man von hier geht. Was wäre die richtige Art und Weise c2gcontroller.js und c2gbcontroller.js zum Prototyp?

Antwort

2

Wie wäre es Pseudo Erbe mit 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

Dies ist, wo eine Kombination von JavaScript awesomeness verwenden und die controller as Syntax kommt wirklich praktisch.

Wenn wir Ihre gemeinsamen Funktionen heraus in ein einfaches altes Objekt ziehen:

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

Dann, wenn wir unsere Controller Refactoring ein normales JS Objekt zu sein, haben wir es mit einem mixin eines von zwei Arten vermehren können. Entweder direkt auf das Objekt selbst oder über den Prototyp.

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

Der größte Unterschied ist, dass jetzt können Sie nur den Controller Referenz direkt über die Verwendung der controller as Syntax.

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

Vielen Dank für Ihre fundierte Antwort!Ich entschied mich dafür, mit user2264997 zu antworten, da es das Yeoman-Benennungsschema nicht durchbricht. – mles