Angular:如何从工厂广播?

时间:2015-05-20 14:28:20

标签: angularjs

我有一个项目列表,每当添加新项目时,我都需要在导航栏中收到一条消息(说明项目已添加!)。

函数addItem()(在Add Item按钮上单击ng)在ItemFactory中,从那里我似乎无法广播它。

<!doctype html>
<html>
    <head>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
    </head>

    <body ng-app="MyApp" ng-controller="MainCtrl">
        <div>{{ text }}

            <nav class="navbar navbar-inverse" ng-controller="NavCtrl">
                <div class="container">
                    <div class="navbar-header">
                        <a class="navbar-brand" href="#">List of items | {{ alertItemAdded }}</a>
                    </div>
                    <form class="navbar-form navbar-right" role="search">
                        <div class="form-group">
                            <input type="text" class="form-control" ng-model="newItem" placeholder="Add an item">
                        </div>
                        <button type="submit" class="btn btn-primary" ng-click="addItem(newItem)">Add Item</button>
                    </form> 
                </div>
            </nav>

            <div class="container" ng-controller="ContentCtrl">
                <div class="row">
                    <div class="col-xs-12">
                        <form class="form-inline">
                            <div class="form-group">
                                <input type="text" class="form-control" ng-model="newItem" placeholder="Add an item">
                            </div>
                            <button type="submit" class="btn btn-primary" ng-click="addItem(newItem)">Add Item</button>
                        </form>
                        <br />
                        <br />
                    </div>
                </div>

                <div class="row">
                    <div class="col-xs-12">
                        <div ng-repeat="item in items">

                            <form class="form-inline">
                                <div class="form-group">
                                    <div>{{ item }}</div>
                                </div>
                                <button type="button" class="btn btn-default btn-s" ng-click="removeItem($index)">Remove Item</button>
                            </form>

                        </div>
                    </div>
                </div>  
            </div>
        </div>
    </body>
</html>


angular.module('MyApp',[]);

angular.module('MyApp').controller('MainCtrl', function($scope, ItemFactory){

    $scope.text = "Text from the Main Controller";

    $scope.addItem = function(newItem){
        ItemFactory.addItem(newItem);
    }

});

angular.module('MyApp').controller('NavCtrl', function($scope){

    // $on
    $scope.$on('itemAdded', function(event, data){
        $scope.alertItemAdded = data;
    });

});

angular.module('MyApp').controller('ContentCtrl', function($scope, ItemFactory){

    $scope.items = ItemFactory.getItem();

    $scope.removeItem = function($index){
        ItemFactory.removeItem($index);
    }

});

angular.module('MyApp').factory('ItemFactory', function(){

    var items = [
        'Item 1', 
        'Item 2', 
        'Item 3'
    ];

    return {
        getItem : function() {
            return items;
        },
        addItem : function(item){
            items.push(item);
            // $broadcast
            $scope.$broadcast('itemAdded', 'Item added!');
        },
        removeItem : function($index){
            items.splice($index, 1);
        }
    };

});

4 个答案:

答案 0 :(得分:2)

您可以将$ rootScope注入工厂并使用$ broadcast。

angular.module('MyApp').factory('ItemFactory', ["$rootScope", function($rootScope){

    var items = [
        'Item 1', 
        'Item 2', 
        'Item 3'
    ];

    return {
        getItem : function() {
            return items;
        },
        addItem : function(item){
            items.push(item);
            // $broadcast
            $rootScope.$broadcast('itemAdded', 'Item added!');
        },
        removeItem : function($index){
            items.splice($index, 1);
        }
    };

}]);

答案 1 :(得分:1)

这是一个干净利落的解决方案。

请参阅此plunker

让我解释一下这一切是如何运作的。

您的邮件如下所示:

<span ng-if="alertItemAdded.recentAdd">Item added !</span>

只有在&#34; alterITemAdded.recenAdd&#34;是真的。如果需要,您将使用此功能使消息消失。

你的工厂现在看起来像这样:

angular.module('MyApp').service('ItemService', function(){

    var service = {};

    //I'll always wrap my data in a sub object.
    service.notification = {};

    service.notification.recentAdd=false;

    service.items = {};

    service.items.list = [
        'Item 1', 
        'Item 2', 
        'Item 3'
    ];

    service.items.addItem = function(item){
          service.items.list.push(item);
          service.notification.recentAdd=true;
          console.log(service);
    }

    service.items.removeItem = function($index){
          service.items.list.splice($index, 1);
    }

    return service;

});

我使用的是服务而不是工厂。但几乎没有区别,只是品味问题。

这是您的控制器

angular.module('MyApp').controller('MainCtrl', function($scope, ItemService){

    $scope.text = "Text from the Main Controller";

});

angular.module('MyApp').controller('NavCtrl', function($scope, ItemService){

    //IMPORTANT POINT : I bind it the sub object. Not to the value. To access the value i'll use $scope.alterItemAdded.recentAdd
    $scope.alertItemAdded = ItemService.notification;
    //I don't have to redeclare the function. I just bind it to the service function.
    $scope.addItem = ItemService.items.addItem;
});

angular.module('MyApp').controller('ContentCtrl', function($scope, ItemService){

    $scope.items = ItemService.items.list;

    $scope.addItem = ItemService.items.addItem;

    $scope.removeItem = function($index){
        ItemService.items.removeItem($index);
    }

});

重点:

我总是将我的变量绑定到子对象。为什么?事实上,如果我这样做      $ scope.alertItemAdded = ItemService.notifications.recentAdd

当我在我的服务中做这样的事情时

 service.notifications.recentAdd = true;

它将创建一个新变量并将引用放入service.notifications.recentAdd。 $ scope.alertItemAdded绑定到上一个引用,不会看到更新。

这样做:

$scope.alterItemAdded = ItemService.notification

并使用ng-if子句中的值或其他任何内容。我阻止引用链接中断。如果我在服务中

service.notification.recentAdd = true

我将为&#34; recentAdd&#34;创建一个带有新引用的新var。但我对&#34;通知&#34;保持相同的参考。将保留控制器中的绑定,并在视图中更新值recentAdd。

如果您有更多问题可以随意提问。

答案 2 :(得分:-1)

你没有将$ scope注入工厂,实际上你不能使用$ rootScope

答案 3 :(得分:-2)

$broadcast从上到下,因此您应该使用$rootScope对其下方的所有$broadcast元素执行$scope

  • 在工厂中注入$rootScope

  • $ rootScope。$ broadcast('itemAdded,'Item added!')