Angularjs: TypeError: невозможно вызвать метод "insertBefore" из null

Найдите здесь скрипку http://jsfiddle.net/UxYLa/6/

Это упрощенная форма того, что я пытаюсь сделать. Существует две директивы, а вложенная - subDirective, которая динамически создает html-форму на основе выбора (случайного). Если вы нажимаете несколько раз на кнопку, она выдает ниже ошибки

TypeError: Cannot call method 'insertBefore' of null
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js:138:283
    at q (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js:7:332)
    at q.after (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js:138:258)
    at Object.O.(anonymous function) [as after] (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js:139:414)
    at Object.enter (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js:141:226)
    at Object.move (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js:141:360)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js:185:282
    at Object.fn (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js:99:371)

Я нашел ссылку об этом https://groups.google.com/forum/#!msg/angular/dNra_7P2hwU/09-UBn1XxyUJ https://github.com/angular/angular.js/issues/2151, но я использую последнюю стабильную версию.

В чем причина этой ошибки.

Полный код ниже:

script:

var myApp = angular.module('myApp', [])
    .controller('TestController', ['$scope', function ($scope) {
        $scope.data = [{ type: "a", values: [{name:"aa"}, {name: "bb"}]},
          { type: "b", values: [{name:"aa"}, {name: "bb"}]}]
}]);   
myApp.directive('directive', function () {
    return {
        scope: {
            data: "=",
        },
        restrict: 'E',
        controller: function ($scope, $element, $attrs) {
            $scope.random = function(){
                $scope.model = $scope.data[Math.floor(Math.random()*$scope.data.length)];
                console.log($scope.model)
            };
        },
         template: '<div><button ng-click="random()">Random</button><sub-directive data="model"></sub-directive></div>'
    };
});


myApp.directive('subDirective', function ($templateCache, $compile) {
    return {    
         scope: {
            data: "=",
        },
        restrict: 'E', 
        link: function (scope, element, attrs) {
             scope.$watch('data', function (newVal, oldVal) {
                if (newVal) {
                     element.html($templateCache.get(newVal.type + '.html'));
                     $compile(element.contents())(scope);
                 }
             });
        }
    };
});

HTML

  <script type="text/ng-template" id="a.html">
     a.html
  </script>


<script type="text/ng-template" id="b.html">
      <div ng-repeat="itm in data">
          <span ng-if='"string" == itm.type'>
              <input name='{{itm.Name}}'id='{{itm.Name}}' ng-model='model[itm.Name]' type='text'></input>
          </span>
      </div>
  </script>

<div ng-controller="TestController">
    <directive data="data"></directive>
</div>

Ответ 1

Это как-то связано с компиляцией и связанными данными. Я сделал рабочую версию здесь: http://jsfiddle.net/UxYLa/9/

Основные отличия заключаются в b.html

  <div ng-if="data.values">
      <div ng-repeat="itm in data.values">
          <input name='{{itm.name}}' id='{{itm.name}}' ng-model="itm.name" type='text'></input>
      </div>
  </div>

Необходимо взаимодействовать с массивами и ссылаться на него вместо модели, поскольку она находится в области.

Изменить: после некоторого копания есть еще несколько подсказок относительно того, почему происходит ошибка, но не тогда, когда вы завертываете ее в div. Он вызывает это: parent.insertBefore(node, index.nextSibling);, где parent - element.parent вашего ng-repeat. Если у вас нет обертки, родитель имеет значение null.

Это означает, что ошибка возникает всякий раз, когда html, который вы компилируете, имеет часы, которые находятся снаружи шаблона при прямом изменении элемента.

Я также сделал решение, которое не пытается напрямую изменить элемент, а добавляет к нему скомпилированный элемент. Так что все, когда оно проверяется в цикле дайджестов, будет иметь надлежащую структуру. http://jsfiddle.net/UxYLa/12/

Надеюсь, что это помогло.

Ответ 2

У меня было такое же сообщение об ошибке. Я могу исправить это с помощью ссылки на JQuery до Angular в тегах html script.

Ответ 3

У меня была такая же проблема, но я обнаружил, что добавляю class="md-sticky" в тег <md-subheader>, и это означает сказать class="md-no-sticky"

Как только я изменил этот класс, это отсортировало проблему для меня, но у меня также была такая же проблема с использованием ng-repeat, но не внутри него собственного родительского тега, но у меня было! Я просто использовал ng-show="condition" для этого родительского тега, и если этот родительский тег не отображался, это вызовет эту проблему, поэтому я изменил его на ng-if="condition" и это отсортировало эту проблему.

Ответ 4

У меня была одна и та же проблема, и, казалось, она решила удалить класс "ng-view", который у меня был на одном из моих div. Как будто это вызывало конфликт.

У меня было:

<div class="ng-view"> 
  <div ng-view>
    ...

Затем изменилось на:

<div class="ngview">
  <div ng-view>
    ...

Я предполагаю, что ng-view является зарезервированным словом, но я не думал, что это будет затронуто при использовании в качестве класса.

Ответ 5

У меня была такая же проблема при использовании UI-Router, и тег A имел неправильный URL-адрес в атрибуте href, который не был маршрутом.