Angularjs:回调父控制器

时间:2015-09-29 21:21:53

标签: javascript angularjs

请考虑以下代码:它具有带隔离范围的指令myItem。每个项目都会显示一个按钮,该按钮将在指令控制器上调用delete()。我希望在外部控制器中触发refreshAppController)。但是,由于孤立的范围,当然无法找到refresh()函数。

   <html>
    <body ng-app="question">
        <div ng-cloak ng-controller="AppController">
            <my-item ng-repeat="item in list" data="list">
            </my-item>
            <input type="text" maxlength="50" ng-model="new_item" />
            <button ng-click="add(new_item)">+</button>
        </div>
        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
        <script>
         (function () {
             var app;

             app = angular.module('question', []);


             app.controller('AppController', [
                 '$scope', '$http', function ($scope, $http) {
                     $scope.list = [];

                     function refresh(){
                         $http.get('/api/items').then(
                             function(response){
                                 $scope.list = response.data;
                             }
                         );
                     }

                     $scope.add = function(item){
                         $http.post('/api/items', { item: item }).then(refresh);
                     };

                     refresh();
                 }
             ]);

             app.directive('myItem', function() {
                 return {
                     scope: {
                         item: '=data',
                     },
                     // directive template with delete button
                     template: '{{ item }} <button ng-click="delete(item)">-</button>',
                     restrict: 'E',
                     // directive controller with delete function
                     controller: [ '$scope', '$http', function($scope, $http) {
                         $scope.delete = function (card) {

// This is where it goes wrong! refresh does not exist
                             $http.delete('/api/items' + card.id).then(refresh);
                         }
                     }]
                 };
             });
         })();
        </script>
    </body>
</html>

我可以做的一件事是在myItem指令中添加ng-change,但这需要使用ngModelController,这看起来有点过分。

我能想到的其他事情:

  1. onchange: '@'之类的内容添加到指令的scope属性中,然后在html中设置onchange = refresh。在delete函数内调用onchange表达式而不是刷新。但这感觉就像我重新实施ng-change

  2. require: '^AppController'添加到指令中。然后我想我可以直接在父控制器上调用refresh。这似乎违反了松耦合。

  3. 根本不使用隔离范围。这意味着我们从父作用域继承并且refresh可用。但是,我的指令隐含地假设范围将包含item。这也违反松散耦合,但是以隐含的方式。

  4. 所以我的问题是:让父控制器知道它应该刷新其内容的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

IMO,第一种方式是最好的方式。该指令从外部接收函数回调,必要时由指令执行。像这样,两个指令松散耦合。它与ng-change类似,ng-change是ng-model指令使用的属性。

示例:指令

app.directive('myItem', function() {
    return {
        restrict: 'E',
        scope: {
            item: '=data',
            myItemDeleteCallback: '&myItemDeleteCallback'
        },
        template: '{{ item }} <button ng-click="delete(item)">-</button>',
        controller: [ '$scope', '$http', function($scope, $http) {
            $scope.delete = function (card) {
                // This is where it goes wrong! refresh does not exist
                $http.delete('/api/items' + card.id).then(function () {
                    $scope.myItemDeleteCallback();
                });
            }
        }]
    };
});

用法:控制器

app.controller('AppController', ['$scope', '$http', function ($scope, $http) {
    $scope.list = [];

    $scope.refresh = function (){
        $http.get('/api/items').then(
            function(response){
                $scope.list = response.data;
            }
        );
    };

    $scope.add = function(item){
        $http.post('/api/items', { item: item })
            .then($scope.refresh);
    };

    refresh();
}]);

用法:模板

<div ng-cloak ng-controller="AppController">
    <my-item my-item-delete-callback="refresh()" ng-repeat="item in list" data="list">
    </my-item>
    <input type="text" maxlength="50" ng-model="new_item" />
    <button ng-click="add(new_item)">+</button>
</div>