0

Ich habe den folgenden Code in meinem Modul:Ist das die richtige Art, Fabrik an Controller zu binden?

.controller('ModalInstanceCtrl', function($rootScope, $scope, emailService) { 
    $scope.emailService = emailService; // Good or not; if not, why? 
    $scope.showed = false; 
    $rootScope.$watch('showed', function() { $scope.showed = $rootScope.showed; }); // In case you wonder why I did this - I'm using this trick to prevent watch from firing twice, because that would happen if I remove the watch below and put its code here. 
    $scope.$watch('showed', function() { 
     if (!$rootScope.showed) return; 
     $scope.selected = 0; 
     $scope.primary = true; 
     $scope.verified = true; 
     if (emailService.emails.length == 0) emailService.load(); 
    }); 
    $scope.EmailSelected = function() { 
     emailService.setCurrent($scope.selected); 
     $scope.primary = emailService.emails[$scope.selected].primary; 
     $scope.verified = emailService.emails[$scope.selected].verified; 
    }; 
}); 

.factory('emailService', function($resource, $http) { 
    var emails = []; // [{email: '[email protected]', verified: true, primary: false}, ...] 
    var selected = 0; 

    function sendreq(action, email){ 
     $http({ 
      method: 'POST', 
      url: '/email/', 
      data: "action_" + action + "=&email=" + email, 
      headers: {'Content-Type': 'application/x-www-form-urlencoded'} 
     }).then(function(response) { 
      console.log(response.data); 
      return true; 
     }, function(data){ 
      return data; 
     }); 
    } 

    return { 
     emails: emails, 
     selected: selected, 
     setCurrent: function(curr){ 
      selected = curr; 
     }, 
     load: function(){ 
      $resource('/api/email/?format=json').query({}, 
       function success(result) { 
        emails.push.apply(emails, result); 
       }); 
     }, 
     add: function(email) { 
      for (var e in emails) if (emails[e].email == email) return false; 
      return sendreq('add', email); 
     }, 
     remove: function() { 
      sendreq('remove', emails[selected].email); 
     } 
    } 

}) 

Und diesen Code in meinem HTML-Vorlage:

<div ng-repeat="e in emailService.emails"> 
    <input type="radio" ng-model="$parent.selected" ng-value="$index" ng-change="EmailSelected()" id="email_{{ $index }}" name="email"> 
    <label for="email_{{ $index }}" ng-bind='e.email'></label> <span ng-show="e.verified">Verified</span> <span ng-show="e.primary">Primary</span> 
</div> 
<div><button ng-disabled="primary" ng-click="emailService.remove()">Remove</button></div> 
<form novalidate> 
    <input class="form-control" type="email" name="email" ng-model="email" placeholder="Email"> 
    <input type="submit" ng-disabled="email === undefined" ng-click="emailService.add(email)" value="Add Email Address"> 
</form> 

Und ich möchte fragen, ob ich das richtig das Modul und Vorlage zusammengestellt haben, weil Ich arbeite zum ersten Mal mit AngularJS. Insbesondere möchte ich fragen, ob es richtig ist, die gesamte Fabrik an das Oszilloskop zu binden. Auch wenn jemand mehr Zeit hat, kann er sich den anderen Code ansehen, um zu sehen, ob alles richtig ist oder nicht. Fühlen Sie sich frei, irgendwelche Vorschläge über meinen Code zu schreiben.
Vielen Dank im Voraus!

Antwort

0

Warum möchten Sie den gesamten Service binden? Das sehe ich in deinem Code nicht. Sie rufen Teile des Service über den Service-Handler auf. Es ist nicht erforderlich, den gesamten Service auf den Bereich zu legen.

+0

Wenn ich das nicht mache, kann ich Service-Methoden (in meinem Fall 'add' und' remove') nicht aus der HTML-Vorlage aufrufen. – MikiSoft

+0

Sie können Handler am Scope haben, die wiederum die Servicefunktionen aufrufen. – shiv

+0

Warum ist das besser, als einfach den gesamten Service auf das Scope zu setzen? – MikiSoft

1

Es kommt immer auf den Einzelfall an.

Auf diese Weise vorformulierten Wrapper-Methoden

$scope.add = (...args) => emailService.add(...args); 

verzichtet werden kann, sowie ihre Tests in Controller spec.

Ein weiterer Vorteil ist, dass es existierendes Objekt für die richtigen Daten liefert Bindung und Umfang Vererbung von skalaren Anwendungsbereich Eigenschaften:

<parent-scope> 
    <p ng-init="emailService.selected = 0"></p> 
    <child-scope> 
    <p ng-init="emailService.selected = 1"></p> 
    {{ emailService.selected === $parent.emailService.selected }} 
    </child-scope> 
</parent-scope> 

Dies würde sicherlich nicht wie erwartet funktionieren, wenn keine da ist emailService Objekt. Dies ist besonders nützlich, wenn controllerAs-Syntax nicht verwendet wird.

Es ist nichts falsch daran, einen Dienst für den Geltungsbereich verfügbar zu machen - wenn seine API dem Bereich des Controllers entspricht. Und dies kann auf ein Antipattern hindeuten, wenn es das nicht tut - oder wenn es zu viele Dienste gibt, die so missbraucht werden.