Это правильный способ привязки фабрики к контроллеру?

У меня есть следующий код в моем модуле:

.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: 'sample@email.dom', 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);
        }
    }

})

И этот код в моем шаблоне HTML:

<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>

И я хочу спросить, правильно ли я собрал модуль и шаблон, потому что я работаю с AngularJS впервые. В частности, я хочу спросить, правильно ли привязывать всю фабрику к сфере? Также, если у кого-то есть больше времени, он может посмотреть на другой код, чтобы увидеть, все ли правильно или нет. Не стесняйтесь писать любые предложения о моем коде.
Заранее спасибо!

2 ответа

Это всегда зависит от конкретного случая.

Таким образом, стандартные методы обертки

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

могут быть опущены, а также их тесты в спецификации контроллера.

Другое преимущество заключается в том, что он предоставляет существующий объект для правильной привязки данных и наследования области свойств скалярной области действия:

<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>

Это, конечно, не будет работать, как ожидалось, если нет emailService объект. Это особенно полезно, когда синтаксис controllerAs не используется.

Нет ничего плохого в том, чтобы предоставить сервису область действия - если его API соответствует области контроллера. И это может указывать на наличие антипаттерна, если он этого не делает, или если слишком много сервисов используются таким образом.

Почему вы хотите связать весь сервис? Я не вижу необходимости в вашем коде. Вы вызываете части службы, используя обработчик службы, нет особой необходимости помещать всю службу в область действия.