这是将工厂绑定到控制器的正确方法吗?

时间:2016-05-13 13:48:50

标签: angularjs angularjs-scope angularjs-controller angularjs-factory angularjs-templates

我的模块中有以下代码:

.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 个答案:

答案 0 :(得分:1)

它总是取决于具体情况。

这种样式的样板包装方法

$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与控制器作用域相匹配。这可能表明反模式,如果没有 - 或者是否有太多的服务被滥用了。

答案 1 :(得分:0)

为什么要绑定整个服务?我认为你的代码中没有必要这样做。您正在使用服务处理程序调用服务的一部分,没有特别需要将整个服务放在范围内。