Angularjs:回调到父控制器

Angularjs: Callback to parent controller

本文关键字:控制器 回调 Angularjs      更新时间:2023-09-26

请考虑以下代码:它有一个具有隔离作用域的指令myItem。每个项目将显示一个按钮,该按钮将调用指令控制器上的delete()。我希望这能触发外部控制器(AppController)中的refresh。但是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表达式而不是refresh。但这感觉就像我在重新实现ng-change ?

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

  3. 完全不要使用隔离作用域。这意味着我们继承了父作用域,并且refresh是可用的。但是,我的指令隐式地假设作用域将保存一个item。这也违反了松耦合,但以隐式的方式。

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

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

例子:指令

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>