I am new to Angularjs. Want to see if there is any way to just use a child directive as a placeholder for holding content but for really rendering?
I don't want to do rendering in the child directive because I want to let the parent to do everything. So I can have some other special logics in the parent directive.
angular.module('components', []).
directive('tabs', function() {
return {
restrict: 'E',
transclude: true,
scope: {},
controller: function($scope, $element) {
var panes = $scope.panes = [];
$scope.select = function(pane) {
angular.forEach(panes, function(pane) {
pane.selected = false;
});
pane.selected = true;
}
$scope.createPane = function() {
var pane = panes[panes.length-1];
var clonedPane = Angular.copy(pane);
panes.push(clonedPane);
}
this.addPane = function(pane) {
if (panes.length == 0) $scope.select(pane);
panes.push(pane);
}
},
template:
'<div class="tabbable tabs-left">' +
'<ul class="nav nav-tabs">' +
'<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+
'<a href="" ng-click="select(pane)">{{pane.title}}</a>' +
'</li>' +
'<li ng-class="addLink"><a ng-click="createPane()"><i class="icon-plus"></i> tab</a></li>' +
'</ul>' +
'<div class="tab-content">' +
'<div ng-repeat="pane in panes" class="tab-pane" ng-class="{active: selected},{{pane.pclass}}" id="{{pane.id}}">' +
'{{ pane.content }}' +
'</div>' +
'</div>' +
'</div>',
replace: true
};
}).
directive('pane', function() {
return {
require: '^tabs',
restrict: 'E',
scope: { title: 'bind', pclass: 'bind', id: 'bind' },
link: function(scope, element, attrs, tabsCtrl) {
var text = element.text();
tabsCtrl.addPane({
title: scope.title,
pclass: scope.pclass,
id: scope.id,
content: text
});
}
};
})
Corresponding html code:
<tabs>
<pane title="tab 1" id="tab1" pclass="tab">
hello
</pane>
<pane title="tab 2" id="tab2" pclass="tab">
world
</pane>
</tabs>
I tried something like the above but nothing is pushed into panes. Seems like the link function of the child directive (pane) is never called. So as a result, only the link for adding tab is displayed.
Any ideas?
Thanks!
The easiest (though sort of annoying) way to approach this would be to have a template for each pane.
In html:
<tabs>
<pane title="tab 1" id="tab1" pclass="tab" template="pane1-templ">
</pane>
<pane title="tab 2" id="tab2" pclass="tab" template="pane2-templ">
</pane>
</tabs>
<script type="text/ng-template" src="pane1-template">hello</script>
<script type="text/ng-template" src="pane2-template>wolrd</script>
In your directive:
'<div class="tab-content">' +
'<div ng-repeat="pane in panes" class="tab-pane" ng-class="{active: selected},{{pane.pclass}}" id="{{pane.id}}">' +
'<div ng-include src="pane.template"></div>' +
'</div>' +
'</div>'
Or.. have you tried doing this to fix it?
In pane:
var html = elm.html();
//...
pane.html = html;
In tabs:
<div ng-bind-html-unsafe="pane.html"></div>
Perhaps the reason why it is not working is because in your child directive you have no template.. Without a template, the directive does not know where and how to render the directive..
What you could do is have something like
template : '<div style="display:none;" ng-transclude></div>'
in your child template..
and your element.text() should still work!
Without a template.. the linking function would never get the 'element' so your child directive will fail right there..
With the template above it should work..