AngularJS无法读取未定义错误的属性'childNodes'

时间:2022-08-24 13:51:25

Now in the compileNodes function in a sub function in the angular code, there are these lines:

现在在angularNodes函数的角度代码中的子函数中,有以下几行:

} else if (childLinkFn) {
  childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
}

In my custom tabs directive, I am getting the error : Cannot read property 'childNodes' of undefined : when trying to manually compile the template for the directive (in order to dynamically add click functionality to the tabs) with this code:

在我的自定义选项卡指令中,我收到错误:无法读取未定义的属性'childNodes':尝试手动编译指令的模板时(为了动态地向选项卡添加单击功能),使用以下代码:

nucleusAngular.directive('nagTabs', ['$timeout', '$http', '$compile', 'nagDefaults', function($timeout, $http, $compile, nagDefaults){
    return {
        restrict: 'A',
    scope: {
      options: '=nagTabs'
    },
        compile: function() {
            return {
                pre: function(scope, element, attributes) {
                    var template = $('<div />').append($(element).html());
                    scope.options = nagDefaults.getTabsOptions(scope.options);

                    template.find('.tabs .tab').each(function(key, value) {
                        template.find('.tabs .tab:nth-child(' + (key + 1) + ')').attr('ng-click', 'switchTab(\'' + $(this).data('tab') + '\')');
                    });

                    element.html($compile(template)(scope));
                    $(element).addClass('nag-tabs');
                },
                post: function(scope, element, attributes) {
                    var $element = $(element);
                    scope.switchTab = function(tab) {
                        if(angular.isNumber(tab)) {
                            //todo: this should work
                            //tab = $(element).find('.tabs li:nth-child(' + tab + ')').data('tab');
                            tab = $(element).find('.tabs .tab:nth-child(' + (tab + 1) + ')').data('tab');
                    }

                        $(element).find('.tabs .tab').removeClass('active');
                        $(element).find('.tabs .tab[data-tab="' + tab + '"]').addClass('active');

                        $(element).find('.tab-content-item').removeClass('active');
                        $(element).find('.tab-content-item[data-tab="' + tab + '"]').addClass('active');
                    }

                    //load the default tab
                    $timeout(function(){scope.switchTab(scope.options.defaultTab);}, 0);
                }
            };
        }
    }
}]);

HTML:

HTML:

<div nag-tabs="tabsOptions">
    <ul class="tabs">
        <li data-tab="html" ng-click="switchTab('html')">HTML</li>
        <li data-tab="javascript" ng-click="switchTab('javascript')">JavaScript</li>
    </ul>
    <div class="tab-content">
        <div data-tab="html" class="tab-content-item">
            html...
        </div>
        <div data-tab="javascript" class="tab-content-item">
            javascript...
        </div>
    </div>
</div>

Now maybe I am not compiling the template correctly however I have tried every single way I can think of to compile the template and I either get the error I mentioned or the functionality just does not work. After reading around it seems like this error can comes up with having an empty text node. Since I tried everything I could think of in my code, I went into the angular code and modified the three line to look like this (I only modified the first line):

现在也许我没有正确编译模板但是我已经尝试了每一种我能想到的编译模板的方法,我要么得到我提到的错误,要么功能不起作用。阅读后,似乎这个错误可能会出现一个空文本节点。因为我在我的代码中尝试了所有我能想到的东西,所以我进入角度代码并修改了三行看起来像这样(我只修改了第一行):

} else if (childLinkFn && node) {
  childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
}

This verifies that the node actually exists to see if it should call the childLinkFn (while I am not 100% sure the effect of this change, it would seem if node does not equal something, the childLinkFn should not be executed). With this code in place, my tabs code works perfectly (and I have not noticed any other issues in my other directives). I then cloned the angular.js repository and applied this change, built angular, and then executed the unit tests and end 2 end tests and they all passed.

这将验证节点是否实际存在以查看它是否应该调用childLinkFn(虽然我不是100%确定此更改的效果,但是如果节点不等于某个东西,则不应该执行childLinkFn)。有了这个代码,我的标签代码完美地工作(我没有注意到我的其他指令中的任何其他问题)。然后我克隆了angular.js存储库并应用了这个更改,构建了角度,然后执行了单元测试并结束了2个结束测试,它们都通过了。

My question is am I doing something wrong in how I am compiling the template for the tabs of should I submit this code change as a pull request (note I am working on the 1.1.3 version)?

我的问题是我在如何为选项卡编译模板时做错了我应该将此代码更改作为拉取请求提交(注意我正在处理1.1.3版本)?

1 个解决方案

#1


1  

In the end, I have switched the format for the directive. Not exactly sure how this works and returning an object with pre/post does not but it does work. The directive code now looks like this:

最后,我已经切换了指令的格式。不完全确定这是如何工作的并返回一个带有前/后的对象不会,但它确实有效。指令代码现在看起来像这样:

nucleusAngular.directive('nagTabs', ['$timeout', '$http', '$compile', 'nagDefaults', function($timeout, $http, $compile, nagDefaults){
return {
    restrict: 'A',
scope: {
  options: '=nagTabs'
},
    compile: function(element, attributes, transclude) {
  $(element).find('.tabs .tab').each(function(key, value) {
    $(element).find('.tabs .tab:nth-child(' + (key + 1) + ')').attr('ng-click', 'switchTab(\'' + $(this).data('tab') + '\')');
  });

  //element.html($compile(template)(scope));
  $(element).addClass('nag-tabs');

return function(scope, element, attributes) {
    scope.options = nagDefaults.getTabsOptions(scope.options);
    var $element = $(element);
    scope.switchTab = function(tab) {
      if(angular.isNumber(tab)) {
        //todo: this should work
        //tab = $(element).find('.tabs li:nth-child(' + tab + ')').data('tab');
        tab = $(element).find('.tabs .tab:nth-child(' + (tab + 1) + ')').data('tab');
      }

      $(element).find('.tabs .tab').removeClass('active');
      $(element).find('.tabs .tab[data-tab="' + tab + '"]').addClass('active');

      $(element).find('.tab-content-item').removeClass('active');
      $(element).find('.tab-content-item[data-tab="' + tab + '"]').addClass('active');
    }

    //load the default tab
    $timeout(function(){scope.switchTab(scope.options.defaultTab);}, 0);
        }
    }
}
}]);

#1


1  

In the end, I have switched the format for the directive. Not exactly sure how this works and returning an object with pre/post does not but it does work. The directive code now looks like this:

最后,我已经切换了指令的格式。不完全确定这是如何工作的并返回一个带有前/后的对象不会,但它确实有效。指令代码现在看起来像这样:

nucleusAngular.directive('nagTabs', ['$timeout', '$http', '$compile', 'nagDefaults', function($timeout, $http, $compile, nagDefaults){
return {
    restrict: 'A',
scope: {
  options: '=nagTabs'
},
    compile: function(element, attributes, transclude) {
  $(element).find('.tabs .tab').each(function(key, value) {
    $(element).find('.tabs .tab:nth-child(' + (key + 1) + ')').attr('ng-click', 'switchTab(\'' + $(this).data('tab') + '\')');
  });

  //element.html($compile(template)(scope));
  $(element).addClass('nag-tabs');

return function(scope, element, attributes) {
    scope.options = nagDefaults.getTabsOptions(scope.options);
    var $element = $(element);
    scope.switchTab = function(tab) {
      if(angular.isNumber(tab)) {
        //todo: this should work
        //tab = $(element).find('.tabs li:nth-child(' + tab + ')').data('tab');
        tab = $(element).find('.tabs .tab:nth-child(' + (tab + 1) + ')').data('tab');
      }

      $(element).find('.tabs .tab').removeClass('active');
      $(element).find('.tabs .tab[data-tab="' + tab + '"]').addClass('active');

      $(element).find('.tab-content-item').removeClass('active');
      $(element).find('.tab-content-item[data-tab="' + tab + '"]').addClass('active');
    }

    //load the default tab
    $timeout(function(){scope.switchTab(scope.options.defaultTab);}, 0);
        }
    }
}
}]);