0

モジュールに次のコードがあります。

.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 を初めて使用するので、モジュールとテンプレートを正しくアセンブルしたかどうかを尋ねたいと思います。具体的には、ファクトリ全体をスコープにバインドするのが正しいかどうかを尋ねたいですか? また、時間があれば、他のコードを見て、すべてが正しいかどうかを確認できます。私のコードに関する提案を自由に書いてください。
前もって感謝します!

4

2 に答える 2

1

It always depends on particular case.

This way boilerplate wrapper methods

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

can be omitted, as well as their tests in controller spec.

Another benefit is that it provides existing object for proper data binding and scope inheritance of scalar scope properties:

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

This certainly would not work as expected if there's no emailService object. This is particularly useful when controllerAs syntax isn't used.

There's nothing wrong with exposing a service to scope - if its API matches the controller scope. And this may indicate an antipattern if it doesn't - or if there are too many services that are abused like that.

于 2016-05-13T15:09:29.610 に答える