Now in the compileNodes function in a sub function in the angular code, there are these lines:
} 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:
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:
<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.
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)?
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);
}
}
}
}]);