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
Related
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.
I'm using AngularUI Bootstrap like this to create a tabset:
...
<tabset>
<tab heading="First Tab">
<div>First Content Here</div>
</tab>
<tab heading="Second Tab">
<div>Second Content Here</div>
</tab>
</tabset>
...
The code that is output to the page looks like this:
...
<ul class="...">
<li ng-class="..." heading="First Tab" class="...">
<a href ng-click="select()" tab-heading-transclude class="ng-binding">
First Tab
</a>
</li>
<li ng-class="..." heading="Second Tab" class="...">
<a href ng-click="select()" tab-heading-transclude class="ng-binding">
Second Tab
</a>
</li>
</ul>
<div class="tab-content">
<!-- tab contents here -->
</div>
...
The problem I have, is the heading links can't be selected via the keyboard because they're missing a tabindex. Obviously, I can't just add that in because angular is creating the filler HTML for the list, and adding a tabindex to the tab element next to the heading attribute just adds it to the li and not the a tag where it needs to be.
Is there a way to define a tabset and also pass in an attribute like a tabindex to be placed on the navigation (heading) links?
When using a UI Boostrap tabset along with nested sticky states created with ui-router and ui-router-extras, I have an issue where navigating to a tab's state via URL will select the first tab along with the correct tab. It should only activate the tab whose state matches the URL route.
Here's what the tabset looks like:
<div style="position:relative">
<tabset>
<tab heading="Dashboard" ui-sref="LMS.Dashboard" ui-sref-active="active"></tab>
<tab heading="Modules" ui-sref="LMS.Modules" ui-sref-active="active"></tab>
<tab heading="Messages" ui-sref="LMS.Messages" ui-sref-active="active"></tab>
<tab heading="Settings" ui-sref="LMS.Settings" ui-sref-active="active"></tab>
</tabset>
<div ui-view="Dashboard" class="tab-content" ng-show="$state.includes('LMS.Dashboard')">
<h2>Dashboard</h2>
{{test}}
</div>
<div ui-view="Modules" class="tab-content" ng-show="$state.includes('LMS.Modules')">
<h2>Modules</h2>
</div>
<div ui-view="Messages" class="tab-content" ng-show="$state.includes('LMS.Messages')">
<h2>Messages</h2>
</div>
<div ui-view="Settings" class="tab-content" ng-show="$state.includes('LMS.Settings')">
<h2>Settings</h2>
</div>
</div>
I have a plunker here:
http://plnkr.co/edit/sQB58YKntDwNIUpAdLmT?p=preview
To see the issue, select a tab other than 'Dashboard', then reload the "live view" frame.
Another way is to open it in a window, switch the tab, then reload.
I have the same issue. Add active="false" to disable default behavior and use ui-sref-active to add active class.
<tab ui-sref-active="active" active="false">
Edit
While this method seems to works, it produces error because false is not assignable.
Edit 2
Combining ng-init with a local scope variable seems to do the trick.
<tab ui-sref-active="active" active="isActive" ng-init="isActive=false">
In your case, it might be simpler to just add an active variable for each tab. See this plunker:
http://plnkr.co/edit/73lm068buZf851h47FVQ?p=preview
I had exactly the same thing. After searching for while, I decided the "value" ui-bootstrap offers around tabs is not worth the effort. My simple manual implementation:
<ul class="nav nav-tabs">
<li ng-class="{active:$state.current.name == 'properties.edit.basic'}"><a ui-sref="properties.edit.basic">Basic</a></li>
<li ng-class="{active:$state.current.name == 'properties.edit.marketing'}"><a ui-sref="properties.edit.marketing">Marketing</a></li>
<li ng-class="{active:$state.current.name == 'properties.edit.rooms'}"><a ui-sref="properties.edit.rooms">Rooms</a></li>
<li ng-class="{active:$state.current.name == 'properties.edit.images'}"><a ui-sref="properties.edit.images">Images</a></li>
<li ng-class="{active:$state.current.name == 'properties.edit.rates'}"><a ui-sref="properties.edit.rates">Rates</a></li>
<li ng-class="{active:$state.current.name == 'properties.edit.availability'}"><a ui-sref="properties.edit.availability">Availability</a></li>
</ul>
<ui-view></ui-view>
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.
I am using AngularUI tabs as seen in the following sample code below and in this plunker.
http://plnkr.co/edit/YlbrObH4sBlyUFZO2tZh?p=preview
<tabset class="tabbable tabbable-custom tabbable-full-width">
<tab class="active" heading="Latest Customers" href="javascript:;">
<div class="tab-pane active" id="Div1">
Pane 1
</div>
</tab>
<tab heading="Feeds" href="javascript:;">
<div class="tab-pane" id="Div2" href="javascript:;">
<div class="tab-pane active" id="Div3">
Pane 2
</div>
</div>
</tab>
</tabset>
As you can see in the plunker, when the mouse hovers over the "tab", the cursor does not change to your typical pointing finger. The anchor tag that angularui is rendering does not have a href value on it, therefore, it is considered invalid html. if i manually add href="javascript:;" , the cursor works like i want it.
My question is, how can i tell the directive to add a href to the anchor tag? any advice?
Thanks,
Dan
You could add a style that targets the tabs:
.nav-tabs > li > a {
cursor: pointer;
}
just write:
<tabset
class="tabbable tabbable-custom tabbable-full-width"
style="cursor: pointer;"
>
....
Mmh this is weird, I too am using angular-ui tabs in my project. I copied and pasted the exact code you provided and it works just fine.
(see bottom of http://wiredbeast.com/coolframework/docs.html#/activity)
I might remove it later so look quick.
So my guess is that it's something wrong with your bootstrap css. I'm using ui-bootstrap-tpls-0.6.0.min.js, bootstrap.js/css v3.0.0, and https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js for angular