AngularJS - ng-include template behaves differently - angularjs

I'm struggling with understanding why ng-include template seems to break my angular application.
I have some ui bootstrap tab issues with multiple controllers and went with this design which works (note I cannot use the built in tab switching across multiple controllers, so it is hidden):
https://plnkr.co/edit/hCCVFt58OXztZDQtxGIS?p=preview
However, simply moving the nav section to a template breaks the tab switching:
https://plnkr.co/edit/Lbh2Pw2wiZAS6oZTwX47?p=preview
The variable 'active_tab' seems to update correctly... but I'm guessing the scope changes when it is in the template?
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" ng-click="navCollapsed = !navCollapsed">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Title</a>
</div> <!-- end navbar-header -->
<div class="collapse navbar-collapse" uib-collapse="navCollapsed">
<ul class="nav navbar-nav">
<li ng-class="{active: active_tab == 1}" ng-click="active_tab = 1">Tab 1</li>
<li ng-class="{active: active_tab == 2}" ng-click="active_tab = 2">Tab 2</li>
<li ng-class="{active: active_tab == 3}" ng-click="active_tab = 3">Tab 3</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>Selected Tab: {{ active_tab }}</li>
</ul>
</div> <!-- end uib-collapse -->
</nav> <!-- end nav -->
<uib-tabset active="active_tab">
<ng-controller ng-controller="test_controller1">
<uib-tab index="1" heading="tab 1">1: {{ tab1_content }}</uib-tab>
<uib-tab index="2" heading="tab 2">2: {{ tab2_content }}</uib-tab>
</ng-controller>
<ng-controller ng-controller="test_controller2">
<uib-tab index="3" heading="tab 3">3: {{ tab3_content }}</uib-tab>
</ng-controller>
</uib-tabset>

Related

AngularJS - Use multiple controllers across bootstrap tabs

I'd like to divide content with bootstrap tabs. This works fine except the html breaks when I attach the ng-controller in parent elements. Is there a way to use html elements to insert ng-controller without affecting the hierarchy necessary to display tabs in bootstrap?
Working tab layout:
<div ng-app="myApp">
<div class="tab-content">
<div id="tab1" class="tab-pane fade in active">{{ tab1_content }}</div>
<div id="tab2" class="tab-pane fade in">{{ tab2_content }}</div>
<div id="tab3" class="tab-pane fade in">{{ tab3_content }}</div>
</div> <!-- all tab-content -->
</div> <!-- end myApp -->
How I'd like to use my controllers (breaks the tab displays by putting content in all tabs:
<div ng-app="myApp">
<div class="tab-content">
<ng-controller ng-controller="test_controller1">
<div id="tab1" class="tab-pane fade in active">{{ tab1_content }}</div>
<div id="tab2" class="tab-pane fade in">{{ tab2_content }}</div>
</ng-controller> <!-- end test_controller1 -->
<ng-controller ng-controller="test_controller2">
<div id="tab3" class="tab-pane fade in">{{ tab3_content }}</div>
</ng-controller> <!-- end test_controller2 -->
</div> <!-- all tab-content -->
</div> <!-- end myApp -->
Demo: https://jsfiddle.net/L2b4yLfa/
Is this acceptable?
I have initialized the same controller for two tabs. Since its a small window the code snippet output will show mobile view. click on run code snippet -> full page
angular.module('myApp', []);
angular.module('myApp').controller('test_controller1', function($scope) {
$scope.tab1_content = "Tab One Content";
$scope.tab2_content = "Tab Two Content";
});
angular.module('myApp').controller('test_controller2', function($scope) {
$scope.tab3_content = "Tab Three Content";
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle pull-left" data-toggle="collapse" data-target="#myNavbar"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button>
<a class="navbar-brand" href="#">Title</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li class="active"><a data-toggle="tab" href="#tab1">Tab 1</a></li>
<li><a data-toggle="tab" href="#tab2">Tab 2</a></li>
<li><a data-toggle="tab" href="#tab3">Tab 3</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>Testing</li>
</ul>
</div>
</div>
</nav>
<div ng-app="myApp">
<div class="tab-content">
<div id="tab1" ng-controller="test_controller1" class="tab-pane fade in active">{{ tab1_content }}</div>
<div id="tab2" ng-controller="test_controller1" class="tab-pane fade in">{{ tab2_content }}</div>
<div id="tab3" ng-controller="test_controller2" class="tab-pane fade in">{{ tab3_content }}</div>
</div> <!-- all tab-content -->
</div> <!-- end myApp -->
So in the future you would need to share data between the same controller for the two tabs using services.
My solution was to switch to angular bootstrap ui, not use the built-in uib-tabs and use $rootscope to handle the 'active_tab' value.
<style> .uib-tab.nav-item { display:none; } .nav-tabs { border-bottom: inherit; } </style>
<div ng-app="myApp">
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" ng-click="navCollapsed = !navCollapsed">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Title</a>
</div> <!-- end navbar-header -->
<div class="collapse navbar-collapse" uib-collapse="navCollapsed">
<ul class="nav navbar-nav">
<li ng-class="{active: active_tab == 1}" ng-click="active_tab = 1">Tab 1</li>
<li ng-class="{active: active_tab == 2}" ng-click="active_tab = 2">Tab 2</li>
<li ng-class="{active: active_tab == 3}" ng-click="active_tab = 3">Tab 3</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>Selected Tab: {{ active_tab }}</li>
</ul>
</div> <!-- end uib-collapse -->
</nav> <!-- end nav -->
<uib-tabset active="active_tab">
<ng-controller ng-controller="test_controller1">
<uib-tab index="1" heading="heading not displayed">1: {{ tab1_content }}</uib-tab>
<uib-tab index="2" heading="heading not displayed">2: {{ tab2_content }}</uib-tab>
</ng-controller>
<ng-controller ng-controller="test_controller2">
<uib-tab index="3" heading="heading not displayed">3: {{ tab3_content }}</uib-tab>
</ng-controller>
</uib-tabset>
</div>
Demo: https://plnkr.co/edit/36tkl3pCV7hgNz8rbpTq?p=preview

Navbar works but clicked element not highlighted

I generated an AngularJS app with yeoman. The navbar works and when I click on the an element the enw page loads, however the clicked button don't get highlighted.
This is the navbar code
<div class="header">
<div class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#js-navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#!/">myApp</a>
</div>
<div class="collapse navbar-collapse" id="js-navbar-collapse">
<ul class="nav navbar-nav">
<li class="active">1</li>
<li><a ng-href="#!/page2">2</a></li>
<li><a ng-href="#!/page3">3</a></li>
<li><a ng-href="#!/page4">4</a></li>
<li><a ng-href="#!/page5">5</a></li>
<li><a ng-href="#!/page6">6</a></li>
</ul>
</div>
</div>
</div>
</div>
There are many ways you can do this. Here there is one of them
Create a controller and set a var called currentLink like this
//...
.controller('headerCtrl', function($scope){
$scope.currentLink = 1;
$scope.set = function(link){
$scope.currentLink = link;
}
});
//...
now in your html modify your code like this:
<div class="header" ng-controller="headerCtrl">
<!--...-->
<div class="collapse navbar-collapse" id="js-navbar-collapse">
<ul class="nav navbar-nav">
<li ng-class="{'active': currentLink == 1}">1</li>
<li ng-class="{'active': currentLink == 2}"><a ng-href="#!/page2" ng-click="headerCtrl.set(2);">2</a></li>
<li ng-class="{'active': currentLink == 3}" ><a ng-href="#!/page3" ng-click="headerCtrl.set(3);">3</a></li>
<li ng-class="{'active': currentLink == 4}"><a ng-href="#!/page4" ng-click="headerCtrl.set(4);">4</a></li>
<!-- and so on-->
</ul>
<!--...-->
</div>
This way with ng-class you switch from active or not every link and with ng-click you set that link as active when clicked;

angularui navbar dropdown issues in v1.3.3

I am new to angularui and I am trying to create an menu with dropdown.
I have seen an example that works with 0.6.0 version of angularui and angularjs 1.1.5 the dropdown menus work
<html ng-app="plunker">
<body ng-controller="MainCtrl">
<nav class="navbar navbar-default" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" ng-init="navCollapsed = true"
ng-click="navCollapsed = !navCollapsed">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" ng-class="!navCollapsed && 'in'">
<ul class="nav navbar-nav">
<li class="active">Link</li>
<li>Link</li>
<li class="dropdown">
Dropdown <b class="caret"></b>
<ul class="dropdown-menu">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
<li>Separated link</li>
<li>One more separated link</li>
</ul>
</li>
</ul>
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li>Link</li>
<li class="dropdown">
Dropdown <b class="caret"></b>
<ul class="dropdown-menu">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
<li>Separated link</li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</nav>
<p>Hello {{name}}!</p>
</body>
</html>
full example in http://plnkr.co/edit/HkwfL9
However, when I change the dependencies, to angularjs 1.5.5 and angularui 1.3.3 the view is as expected but the dropdowns do not work (http://plnkr.co/edit/rNaNj8gqnrwOwOVnGlD2)
I would greatly appreciate if someone could help me with this.
Thanks a million!

Bootstrap nav-tabs not working with Angular $routeprovider

I am using AngularJs and Bootstrap. While I am using $RouteProvider for SPA, I am using bootstrap for the layout. This is working fine.
However, I am now trying to use Bootstrap nav-tabs to have tab based navigations.
My HTML is like this:
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#/mis"><i class="fa fa-tachometer"></i> TrigonMeter</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div id="navbar" class="navbar-collapse collapse">
<ul id="tabs" class="nav navbar-nav nav-tabs container-fluid" data-tabs="tabs">
<li class="active"><a data-target="#db" href="#db" data-toggle="tab">Dashboard</a></li>
<li><a data-target="#admin" href="#admin" data-toggle="tab">Admin</a></li>
<li><a data-target="#mis" href="#mis" data-toggle="tab">MIS</a></li>
<li><a data-target="#fin" href="#fin" data-toggle="tab">Finance</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="nav-link">Hi {{globals.currentUser.username}}</li>
<li><span class="glyphicon glyphicon-log-out"></span>Logout</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</nav>
For the tabs. This works fine. And the following is the tab-content section:
<div class="container-fluid">
<!--[if lt IE 7]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>
<![endif]-->
<div class="row">
<div id="my-tab-content" class="tab-content col-sm-2 col-md-2 sidebar">
<div class="tab-pane active" id="db">
<h1>Dashboard</h1>
<ul>
<li>Organisation Details</li>
<li>Job Numbers</li>
<li>Job Expenses</li>
<li>Job Financial Details</li>
<li>Contracts</li>
</ul>
</div>
<div class="tab-pane" id="admin">
<h1>Admin</h1>
<p>Organisation Details</p>
</div>
<div class="tab-pane" id="mis">
<h1>MIS</h1>
<ul>
<li>Job Numbers</li>
<li>Job Expenses</li>
<li>Job Financial Details</li>
<li>Contracts</li>
</ul>
</div>
<div class="tab-pane" id="fin">
<h1>Finance</h1>
<p>orange orange orange orange orange</p>
</div>
</div>
<div class="col-sm-10 col-md-10">
<div ng-view></div>
</div>
</div>
</div>
But The tab-content section is not working.
Please do let me know if I could explain the problem.
Is there a way to do this?

AngularJS with Bootstrap 3 navbar not collapsing on small device and hash tag links

So the problem comes when trying the project I'm working on the phone, the links I have inside my navbar are all with hash tag links (#) since it's AngularJS... Now I did find a way to make it to work perfectly in jQuery
$('.nav li a').not('.dropdown-toggle').on('click', function(){
$('.navbar-ex1-collapse').removeClass('in').addClass('collapse');
});
but since they always say to stop using plain jQuery or DOM manipulation...so how am I suppose to do this? I'm new to AngularJS and I'm not to good at starting to create my own directive, or should I just have $watch? but then how can I watch a certain class to be clicked then? I tried to do this example twitter-boostrap-navbar-with-angular-js-collapse-not-functioning but it was made specifically for Bootstrap 2.3 and some properties have changed too, so I'm getting a little confused. I could leave the jQuery, but you know...I'm trying to learn the proper way of doing... :)
Oh and if that help, my navbar Bootstrap 3 menu looks like this
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
Portfolio<b class="caret"></b>
<ul class="dropdown-menu">
<li>Add</li>
<li>Undo</li>
<li>List</li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container -->
</nav>
Probably a bit late, but here is a bootstrap 3.x version of the answer I gave in the question you referenced - http://jsfiddle.net/N99dQ/
This time, I have used ng-init instead of a controller, but both ways will work. Also worth mentioning, if you are not using the dropdowns, you'll only need to include ['ui.bootstrap.collapse']
HTML:
<nav id="navbar-example" class="navbar navbar-inverse navbar-static" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button class="navbar-toggle" type="button" ng-init="isCollapsed = true" ng-click="isCollapsed = !isCollapsed">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project Name</a>
</div>
<div collapse="isCollapsed" class="navbar-collapse bs-js-navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a id="drop1" href="#" role="button" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop1">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
</ul>
</li>
<li class="dropdown">
Dropdown 2 <b class="caret"></b>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop2">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li id="fat-menu" class="dropdown">
Dropdown 3 <b class="caret"></b>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop3">
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>
</div><!-- /.nav-collapse -->
</div><!-- /.container-fluid -->
</nav>
Javascript:
var myApp = angular.module('myApp', ['ui.bootstrap']);
As an alternate to my previous answer, this one uses ng-repeat to condense the html. http://jsfiddle.net/m5TZw/
HTML
<div class="container-fluid">
<div class="navbar-header">
<button class="navbar-toggle" type="button" ng-click="isCollapsed = !isCollapsed">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project Name</a>
</div>
<div collapse="isCollapsed" class="navbar-collapse bs-js-navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a id="drop1" href="#" role="button" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop1">
<li ng-repeat="m in menu1" role="presentation"><a ng-click="go(m.link)" role="menuitem" tabindex="-1">{{m.text}}</a></li>
</ul>
</li>
<li class="dropdown">
Dropdown 2 <b class="caret"></b>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop2">
<li ng-repeat="m in menu1" role="presentation"><a ng-click="go(m.link)" role="menuitem" tabindex="-1">{{m.text}}</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li id="fat-menu" class="dropdown">
Dropdown 3 <b class="caret"></b>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop3">
<li ng-repeat="m in menu1" role="presentation"><a ng-click="go(m.link)" role="menuitem" tabindex="-1">{{m.text}}</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
JS
var myApp = angular.module('myApp', ['ui.bootstrap.collapse', 'ui.bootstrap.dropdownToggle']);
function NavBarCtrl($scope, $location) {
$scope.isCollapsed = true;
$scope.menu1 = [
{text: 'first', link : '/first'},
{text: 'second', link : '/second'},
{text: 'third', link : '/third'},
{text: 'fourth', link : '/fourth'},
{text: 'fifth', link : '/fifth'}
];
$scope.go = function(path) {
$scope.isCollapsed = true;
$location.path('#/' + path);
}
}
Rather importing a heavy "ui.bootstrap" I feel that this will be simple JS fix:
//for close, opened dropdown.
$(".nav a").click(function () {
if ($(".navbar-collapse").hasClass("in")) {
$('[data-toggle="collapse"]').click();
}
});
If this code is not working correctly then see that it's binding correctly, so place it in controller that loads page.

Resources