How to use tabs with separate controllers? - angularjs

In my Angular 1.3 project I have the following:
<tabset>
<tab ng-controller="FirstTabCtrl">
{{content}}
</tab>
<tab ng-controller=SecondTabCtrl">
{{content}}
</tab>
</tabset>
In Angular 1.4.4 I get the following error message:
Multiple directives [ngController, tab] asking for new/isolated scope
I have tried wrapping the tabs in div's but that destroys the layout.
How can rewrite the code to work with 1.4.4?
Here is a plunker describing the problem: http://plnkr.co/edit/KScdI2jAZ4BAvDL4kCfk?p=preview

If you definitely don't want to use routes and states to handle the tabs, you could restructure the content inside each tab directive: add the ng-controller to a div inside the <tab> element, like this:
<tab heading="tab 1">
<div ng-controller="FirstCtrl">
{{content}}
</div>
</tab>
Here's a plunkr to show it.
This doesn't destroy the tab layout, but if it does in some way, you can always handle that with CSS.

Related

Add image in tab using Bootstrap directives for AngularJS

I have used bootstrap directive for angularjs for tab(http://angular-ui.github.io/bootstrap/),
and i found that it only support specific parameters
https://github.com/angular-ui/bootstrap/tree/master/src/tabs/docs
i want to know is there any way to set image instead of heading for bootstrap angularjs directive ?
Check it out here:
<tabset>
<tab>
<tab-heading>
<i class="glyphicon glyphicon-bell"></i> Alert!
</tab-heading>
Other tab content
</tab>
</tabset>
Practically you can put any content inside the <tab-heading>.

Angularjs bootstrap tabset tab heading

I am wondering whether it is possible to write html inside an angularjs bootstrap tabset tab heading. I am trying to add a svg inside the title. I have created a quick snippet in plunker to try and demonstrate the issue I am having.
<tabset>
<tab heading="<span>hello</span><em>1</em>">One</tab>
<tab heading="Two">Two</tab>
<tab heading="Three">Three</tab>
</tabset>
http://plnkr.co/edit/qFsFGDNUIJj9nIF51ApU
any ideas?
thanks
Angular Bootstrap v0.14+
Angular Bootstrap v0.14 introduced new prefixes for most previously provided controls. The original answer below still applies, but you must use the new tag names uib-tabset, uib-tab, and uib-tab-heading.
<uib-tabset>
<uib-tab>
<uib-tab-heading>
<span>hello</span><em>1</em>
</uib-tab-heading>
One
</uib-tab>
<uib-tab heading="Two">Two</uib-tab>
<uib-tab heading="Three">Three</uib-tab>
</uib-tabset>
Angular Bootstrap < v0.14
You should be using the tab-heading element within the tab element if you want HTML within the heading (as shown in the example in the docs):
<tabset>
<tab>
<tab-heading>
<span>hello</span><em>1</em>
</tab-heading>
One
</tab>
<tab heading="Two">Two</tab>
<tab heading="Three">Three</tab>
</tabset>
Updated plunker here.
Since 2016
The accepted answer is ok for the ui-bootstrap prior version 0.14.0, since version 0.14.0 (2015.10.09) tabs use uib- prefix.
See changelog
So you have to replace all tags with uib- prefix
<uib-tabset>
<uib-tab>
<uib-tab-heading>
<span>hello</span><em>1</em>
</uib-tab-heading>
One
</uib-tab>
<uib-tab heading="Two">Two</uib-tab>
<uib-tab heading="Three">Three</uib-tab>
</uib-tabset>
You can give your TAB tag an id and then use jQuery to augment the html.
...tab id="myid"....
and then
jQuery("#myid").html("New Html")
[edit] Taylor Buchanan's answer is the correct answer!
Looking at the template used by the tabs directive, the headings content will be escaped: https://github.com/angular-ui/bootstrap/blob/192768e109b5c4a50c7dcd320e09d05fedd4298a/template/tabs/tab.html#L2
So it is not possible to use html in your headings.
You can create a work-around by re-defining the tab template like so:
angular.module("template/tabs/tab.html").run(["$templateCache", function($templateCache) {
$templateCache.put("template/tabs/tab.html",
"<li ng-class=\"{active: active, disabled: disabled}\">\n" +
" <a ng-click=\"select()\" tab-heading-transclude ng-bind-html=\"heading\"></a>\n" +
"</li>\n" +
"");
}]);
You will also need to nclude angular-sanitize.js to safely bind html contents.
Working Demo here: http://plnkr.co/edit/ep5f1GY12vSixT4xtxFy?p=preview
<li heading="Status" class="ng-isolate-scope var" ng-model="(var = 'active: active')" >
Status1
</li>
<li heading="Status" class="ng-isolate-scope var" ng-model="var = 'active: active'">
Status
</li>
</tabset>

ng-if and angular ui $parent error

I have a simple layout using Angular UI tabs as follows:
<div id="mainContainer" class="mainContainer" data-ng-controller="authorization">
<tabset ng-if="authorized">
<tab heading="Resources" >
Authorized
</tab>
</tabset>
<div ng-if="!authorized">
Not authorized
</div>
</div>
Whenever authorized is false "Not authorized" is displayed is expected, but whenever authorized is true and tabs are supposed to be display I get this ugly thing:
TypeError: Cannot read property '$parent' of undefined
at link (http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.7.0.js:2760:51)
at Q (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js:49:451)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js:56:142
at f (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js:43:24)
at Q (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js:49:392)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js:56:142
at f (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js:43:3)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js:42:180
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js:43:422
at y (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js:47:204) <ul class="nav {{type && 'nav-' + type}}" ng-class="{'nav-stacked': vertical}" tabset-titles="!tabsAbove">
I also get the same thing if I use ng-switch.
Here is the Angular versions I am using
//ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js
//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.7.0.js
Seeing how it doesn't look like it's coming from any of my angular code I am not even sure where to start looking for a solution.
Thank you!
One solution is to ensure that the directives ng-if and tabset do not collide:
<div ng-if="authorized">
<tabset>
<tab heading="Resources" >
Authorized
</tab>
</tabset>
</div>
Your problem could be related to this issue.

AngularJS advanced tabs - two ng-transclude

Angular UI, has support only for basic tabs.
I wanted to create a directive that would support nested tabs & advanced headings (that can include html).
I think, that the best syntax would be
<tabs>
<tab>
<title><i class="myIcon"></i> Title 1</title>
<p>Content 1</p>
</tab>
<tab>
<title class="pull-right">Title 2 (Nested)</title>
<tab>
<title>Title 2.1</title>
<p>Content 2.1</p>
</tab>
<p>Content 2</p>
</tab>
</tabs>
My problem with this approach, is that I would need 2 ng-transclude - one for panes and one for titles.
As it would be very easy to do the first ng-transclude (just like in the tutorial):
<div>
<ul>
<li ng-repeat="pane in panes" transclude-title></li>
</ul>
<div class="tab-content" ng-transclude="">
</div>
</div>
I don't have any idea how can I transclude titles here?
How can I preserve nested structure of tabs ?
Maybe there is a better solution to this problem ?
This is a multiple transclude example. I hope it points you into the right direction.
http://plnkr.co/edit/wpgvgr5h6nAQDOZYEHNI?p=preview

angular-ui tabs loading template in tab-content

I'm using the tabs in angular-ui using this controller:
$scope.panes = [
{ title:"Home", content:"home" , active: true},
{ title:"Settings", content:"settings"},
{ title:"View", content:"view"}
];
and this in the html file:
<tabs>
<pane
active="pane.active"
heading="{{pane.title}}"
ng-repeat="pane in panes"
>
{{pane.content}}
</pane>
</tabs>
but i want to set the content as a template how can I do that, I tried setting the ng-include code in this plunker, but didn't work.
Thanks in advance.
update:
if you find this solution and you'r not using angular-bootstrap v0.12 you need to update the code to the new syntax of v0.13 like this:
<tabset>
<tab
active="pane.active"
heading="{{pane.title}}"
ng-repeat="pane in panes"
>
<div ng-include="pane.content"></div>
</tab>
</tabset>
I already updated the plunker to have the syntax of the angular-bootstrap v0.13.
Just add the ng-include as a child of the pane
<tabs>
<pane active="pane.active"
heading="{{pane.title}}"
ng-repeat="pane in panes">
<div ng-include="pane.content"></div>
</pane>
</tabs>
The reason this works is that the scope variable pane is not yet available when you use the ng-include in the same element as the ng-repeat that creates the pane variable.
This is because the priority value of the ng-include is 0(the default) while the priority of the ng-repeat is 1000 and so the order of execution is:
ng-include
ng-repeat
See the directive docs

Resources