AngularJS:由其父级附加的子指令找不到其父级的控制器

AngularJS: Child directive that is appended by its parent cannot find its parent's controller

提问人:Kory 提问时间:4/30/2014 最后编辑:Kory 更新时间:4/30/2014 访问量:431

问:

我正在构建一个指令,该指令将创建一个输入列表。当您开始在第一个输入中输入信息时,一个空输入将附加到您正在处理的输入下方。

我有这个 plunkr 为第一个输入工作。麻烦的是第二个输入不会附加任何内容。

我收到此错误:错误:$compile找不到指令“child”所需的控制器“parent”!

我怀疑我需要以不同的方式添加新输入,但我不确定如何。

我已经查看了 Stack Overflow 上的其他帖子,它们对走到这一步很有帮助,但它们都没有解决与父控制器保持通信的问题。

下面是父指令:

app.directive('parent', function() {
  return {
    restrict: 'AE',
    template: '<child name="0"></child>',
    controller: function($scope, $compile, $element) {

      // adds a new input within the parent 
      this.addChild = function(counter) {
        $element.append($compile('<child name="' + counter + '"></child>')($scope));
      }
    }
  }
});

下面是子指令:

app.directive("child", function() {
  return {
    restrict: "E",
    scope: {},
    replace: true,
    require: '^parent',
    controller: function($scope, $attrs) {

      $scope.x = $attrs;
      $scope.directiveModel = "";

      $scope.$watch('directiveModel', function() {
        $scope.$parent.myModel[$attrs.name] = $scope.directiveModel;
      });

    },
    template: '<div><input type="text" name="{{x.name}}"  ng-model="directiveModel"></div>',
    link: function($scope, $element, attr, parentCtrl) {
      var fieldCounter = 0;
      var oldLength = 0;
      $scope.$watch('directiveModel', function() {
        // logic to determine if a new input needs to be added based on directiveModel's length
        // only add inputs when directiveModel.length is going from 0 to 1
        if ($scope.directiveModel.length == 1) {
          if (oldLength === 0) {
            fieldCounter++;
            parentCtrl.addChild(fieldCounter);
          }
        } else if ($scope.directiveModel.length === 0) {
          if (oldLength == 1 && fieldCounter > 0) {
            fieldCounter--;
            $element.remove();
          }
        }

        oldLength = $scope.directiveModel.length;
      }, true);
    }

  };
});

这是标记

  <body ng-controller="MainCtrl">
    <parent></parent>

    <pre>{{myModel | json}}</pre>
  </body>
angularjs 父子 using 指令

评论

0赞 km6zla 4/30/2014
请在您的问题中添加代码,而不仅仅是 plunkr
0赞 Stefan Falk 4/30/2014
就像 ogc-nick 说的:请添加你的代码

答:

0赞 z.a. 4/30/2014 #1

观察: - 如果您继续在第一个字段上输入,然后删除所有内容,请再次写入。它成功地不断创建新的输入字段 - 我认为问题出在范围上。您的第一个子指令(父模板中的子指令)创建一个范围,该范围实际上是父指令的作用域,但所有其他指令都有自己的作用域。在 Dev Tools 的 Inspect 元素上检查它。 - 我还尝试了 emit 和 on。相同的结果。 - 因此,只有您的第一个指令是健康创建的,并且它会不断创建新的孩子。也许试着从那里开始。

0赞 Kory 4/30/2014 #2

我放弃了父子指令的整个想法。取而代之的是,我使用了一个处理所有数据操作的指令,并对存储的数据执行了 ng-repeat。

这是我的 app.js 文件

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

app.controller('MainCtrl', function($scope, $compile, $element) {
  $scope.myModel = [
                    {
                        value: ""
                    }
    ]; 
});

app.directive("stackingInput", function() {
    return {
        restrict: "E",
        scope: {
            item: "=",
            index: "="
        },
        replace: true,
        template: '<div><input type="text" ng-model="item.value"></div>',
        controller: function($scope, $element, attr){
            var fieldCounter = 0;
            var oldLength = 0;
            $scope.$watch('item', function() {
                    if ($scope.item.value.length == 1) {
                        if (oldLength === 0) {
                            fieldCounter++;
                            $scope.$parent.myModel.push({value: ""});
                        }
                    } 
                    else if ($scope.item.value.length === 0) {
                        if (oldLength == 1 && fieldCounter > 0) {
                            fieldCounter--;
                            $scope.$parent.myModel.splice($scope.index, 1);
                        }
                    }

                    oldLength = $scope.item.value.length;                   
            }, true);
        }
    };
});

然后,您可以将此行添加到ng-controller元素中的标记中

<stacking-input ng-repeat="item in myModel" item="item" index="$index"></stacking-input>