I'd like to use ng-include in the content of a dynamically generated tab using AngularJs and UI Bootstrap.
I have a Plunker here: http://plnkr.co/edit/2mpbovsu2eDrUdu8t7SM?p=preview
<div id="mainCntr" style="padding: 20px;">
<uib-tabset>
<uib-tab ng-repeat="tab in tabs" active="tab.active" disable="tab.disabled">
<uib-tab-heading>
{{tab.title}} <i class="glyphicon glyphicon-remove-sign" ng-click="removeTab($index)"></i>
</uib-tab-heading>
{{tab.content}}
</uib-tab>
</uib-tabset>
</div>
JS Code:
$scope.addTab = function() {
var len = $scope.tabs.length + 1;
var numLbl = '' + ((len > 9) ? '' : '0') + String(len);
var mrkUp = '<div>' +
'<h1>New Tab ' + numLbl + ' {{foo}}</h1>' +
'<div ng-include="tab.tabUrl" class="ng-scope"></div>' +
'</div>';
$scope.tabs.push({title: 'Tab ' + numLbl, content: $compile(angular.element(mrkUp))($scope)});
}
In the Plunker, click the "Add Tab" button. It calls a function in $scope that pushes a new tab to the collection but passing in some dynamically generated content that includes a ng-include directive. The expected output is that the ng-include will be displayed inside of the tab content area.
Thanks
In your Plunker you are using ng-bind-html
which doesn't compile the HTML for you. You can create a new directive that does that for you.
Source code for ng-bind-html
:
var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {
return {
restrict: 'A',
compile: function ngBindHtmlCompile(tElement, tAttrs) {
var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
return (value || '').toString();
});
$compile.$$addBindingClass(tElement);
return function ngBindHtmlLink(scope, element, attr) {
$compile.$$addBindingInfo(element, attr.ngBindHtml);
scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
// we re-evaluate the expr because we want a TrustedValueHolderType
// for $sce, not a string
element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
});
};
}
};
}];
Pick a name for the new directive, for example compile-html
.
Replace tAttrs.ngBindHtml
with tAttrs.compileHtml
(or whatever name you picked).
You need to replace $sce.getTrustedHtml
with $sce.trustAsHtml
, or you will get Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.
Then you need to call $compile
:
$compile(element.contents())(scope);
Full directive:
app.directive('compileHtml', ['$sce', '$parse', '$compile',
function($sce, $parse, $compile) {
return {
restrict: 'A',
compile: function ngBindHtmlCompile(tElement, tAttrs) {
var ngBindHtmlGetter = $parse(tAttrs.compileHtml);
var ngBindHtmlWatch = $parse(tAttrs.compileHtml, function getStringValue(value) {
return (value || '').toString();
});
$compile.$$addBindingClass(tElement);
return function ngBindHtmlLink(scope, element, attr) {
$compile.$$addBindingInfo(element, attr.compileHtml);
scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
element.html($sce.trustAsHtml(ngBindHtmlGetter(scope)) || '');
$compile(element.contents())(scope);
});
};
}
};
}
]);
Usage:
<div compile-html="tab.content"></div>