angularjs bootstrap tabs are not changing after first time dynamically - angularjs

<ul class="nav nav-tabs nav-tabs-simple" role="tablist">
<li class="nav-item">
A
</li>
<li class="nav-item">
B
</li>
<li class="nav-item">
C
</li>
</ul>
And then the actual tabs:
<div class="tab-pane" ng-class="{'active': activeTab =='main'}" id="atab">
</div>
<div class="tab-pane" ng-class="{'active': activeTab =='main'}" id="btab">
</div>
<div class="tab-pane" ng-class="{'active': activeTab =='main'}" id="ctab">
</div>
So this is working for me the first time, I'm able to switch to the 2nd tab programatically:
$scope.activeTab = 'b';
But when I go back manually to tab 'a' and fire a command which calls the same function the active class remains on the first tab and is not changing programmatically.
So, I want to know what am I doing wrong, and why I'm able to navigate only the first time but not after that.

First, the active class should be applied to the li element, NOT the a anchor tag. Also, you have set all your divs to activate when activeTab is "main", and not the corresponding letters:
<li class="nav-item" ng-class="{active: activeTab =='a'}">
A
</li>
<div class="tab-pane" ng-class="{'active': activeTab =='a'}" id="atab">
</div>
<div class="tab-pane" ng-class="{'active': activeTab =='b'}" id="btab">
</div>
<div class="tab-pane" ng-class="{'active': activeTab =='c'}" id="ctab">
</div>
Secondly, the tab functionality of plain Bootstrap uses jQuery to change classes. jQuery operates completely outside of AngularJS's "digest cycle". This means AngularJS has no control or knowledge over things that happen whey you click the tab headers. This will cause some unexpected behavior.
That is why this library was created to take full advantage of Bootstrap and AngularJS integration: https://angular-ui.github.io/bootstrap/#!#tabs
Here is a semi-working example of your code, that illustrates the jQuery/AngularJS digest cycle problems: https://plnkr.co/edit/tBgvPjJ9HVvSj1SIrWhG?p=preview

Related

open dropdown with ng-class Angularjs and typescript

I need to open the dropdown when clicking on link with angularjs. my idea is to add the class open to the dropdown with ng-class directive but this is not working .
I have two dropdown menu, what i need is to open the second one when clicking on the link within the first one
<ul class="nav navbar-nav navbar-right " >
<li class="dropdown" ng-class="myDropdown ? : 'open'">
<a class="dropdown-toggle" data-toggle="dropdown" >Menu</a>
<ul class="dropdown-menu " role="menu" ng-if="!myDropdown">
<li>
Open second dropdown
</li>
</ul>
<ul class="dropdown-menu " role="menu" ng-if="myDropdown">
<li >
Go back
</li>
</ul>
</li>
</ul>
Typescript
toogleDropDown() {
this.scope.myDropdown = true;
}
This won't work since you toggleDropDown is a function and it does not return anything !undefined should be true I think so your line:
Go back
is same as writing:
Go back
overall there's no need for that function at all what you need is something like this:
<a href="" ng-click="myDropdown=!myDropdown">
<span ng-if="!myDropdown">Open second dropdown</span>
<span ng-if="myDropdown">Go back</span>
</a>
and remove that function from your controller there's no need for it.
also I believe you wanted to set up ng-class like this:
<li class="dropdown" ng-class="{'open': myDropdown}">
Here's fiddle: https://jsfiddle.net/pegla/nq11093m/1/

Dealing with conflicting IDs in multiple instances of bootstrap tabs

I'd like to have multiple instances of the same bootstrap tab markup in the DOM. Unfortunately it appears that bootstrap tabs mandate the use of IDs which means the same IDs conflict as IDs should by definition only occur once in the DOM tree.
Example, see jsfiddle, the bottom Foo Bar tabs end up controlling the top tab pane since I've added multiple elements to the DOM with the same ID.
<div>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">Foo</li>
<li role="presentation">Bar</li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="foo">Foo content</div>
<div role="tabpanel" class="tab-pane" id="bar">Bar content</div>
</div>
</div>
<div>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">Foo</li>
<li role="presentation">Bar</li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="foo">Foo content</div>
<div role="tabpanel" class="tab-pane" id="bar">Bar content</div>
</div>
</div>
As I'm using Angular, as with any template engine, I can differentiate the IDs in the template with a scope variable and ensure that variable is unique throughout my application. Example, using {{id}} as a suffix.
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">Foo</li>
<li role="presentation">Bar</li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="foo{{id}}">Foo content</div>
<div role="tabpanel" class="tab-pane" id="bar{{id}}">Bar content</div>
</div>
I'd like to know if there is a nicer way to solve this problem? Any way of configuring bootstrap to use class based selectors etc?
Check out the ui-bootstrap package. It makes dealing with tabs way easier in Angular.

angular-ui-tree click doesn't work

I downloaded the angular-ui-tree package and installed it in a webserver. I can bring up the example pages fine in my browser, but all the click actions on the buttons (to collapse/expand the tree, add node etc) do not work. I don't get any errors in firebug.
If I point my browser at the public page for the tree component ( https://jimliu.github.io/angular-ui-tree/index.html) it does work.
I did some debugging and found that the problem is when ng-repeat is called for a ui-tree-node element, an ng-click action does not work.
In the code below, the test() function is in my controller and it gets executed if I remove the ui-tree-node or ng-repeat tags.
<li ui-tree-node ng-repeat="node in mydata" >
<a ng-click="test()" >{{node.title}} </a>
</li>
Is this a bug in angular tree component?
Is there some way I can fix this in my environment?
The fix was to add the data-nodrag tag in the top level ui-tree-nodes element.
(adding data-nodrag in the li element also works).
You can use both:
click with toggle(this)
drag
together, just make sure that the element to expand/collapse ist not within the ui-tree-handle
<script type="text/ng-template" id="tree_renderer.html">
<div ng-class="{collapsed: collapsed}">
<div class="ctx_node"
ui-on-drop="onDrop($event, $data, ctx,node); active=false">
<span class="expanded"
ng-click="toggle(this)"
ng-class="{'collapsed': collapsed,'expanded': !collapsed}">
</span>
<span ui-tree-handle>{{node.title}}</span>
</div>
</div>
<ol ui-tree-nodes="" ng-model="node.nodes">
<li ng-repeat="node in node.nodes"
ui-tree-node ng-include="'tree_renderer.html'">
</li>
</ol>
</script>
<div ui-tree data-drag-enabled>
<ol ui-tree-nodes="" ng-model="node.nodes" id="tree-root">
<li ng-repeat="node in node.nodes"
ui-tree-node ng-include="'tree_renderer.html'"></li>
</ol>
</div>

How to make dynamic dropdown menu?

<ul class="nav navbar-nav friend-label">
<li class="dropdown" ng-repeat="module in modules">
<a href="" class="dropdown-toggle" data-toggle="dropdown">
{{module.ModuleName}} <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li ng-repeat="subModule in module.SubModules">
<a href=""><b>{{subModule.SubModuleName}} </b>
</a>
</li>
</ul>
</li>
</ul>
By which, I'm getting following out put.
Question and problem is, when I do have submenu its fine if dropdown appears,
but when there is no submenu, dropdown should not come. still it shows dropdown small pointer arrow. and if you click it, it comes out with blank dropdown.
As shown in this fig, Contact Us menu doesn't have submenu. Still blank dropdown comes. I want to stop it using above code of HTML. Its a small problem. but I'm unable to fig it out.
Using ngRepeat you can dynamically populated menu from the model:
<span class="dropdown" dropdown on-toggle="toggled(open)">
<a href class="dropdown-toggle" dropdown-toggle>
Click me!
</a>
<ul class="dropdown-menu">
<li ng-repeat="choice in items">
<a ng-click="runFn(choice.fn)">{{choice.name}}</a>
</li>
</ul>
</span>
Look for fully worked example on Plunker
I am inferring that you are populating your dropdown items dynamically via ajax or server-side.
If that is true, then you could make use of small CSS/Javascript to hide empty menus. But, you have to take care of a few quirks.
First make sure that your markup looks like this:
<li class="dropdown">
Contact Us <span class="caret"></span>
<ul class="dropdown-menu" role="menu"></ul>
</li>
Important: Notice, that there is no white space between your ul.dropdown-menu start and end tags. This is because, the CSS :empty selector will fail if there is a white-space or line-break.
Now, if there are menu-items in your database you could populate those inside the ul.dropdown-menu as li. If there are no items, then it will left empty. At this point you will have a small dropdown which is empty and still a caret showing.
A little CSS can make the empty dropdown go away:
ul.dropdown-menu:empty {
display: none;
}
But, because CSS does not have reverse adjacent sibling combinator, we cannot target the caret. So, we have to resort to a little Javascript/jQuery:
$("ul.dropdown-menu:empty").prev("a").children("span.caret").first().hide();
You can choose to have both implemented only in jQuery if you wish to. This is just to give you an idea.
Put together your setup now looks and behaves something like this snippet below. Please view it in full-screen to prevent collapsing.
Snippet:
$("ul.dropdown-menu:empty").prev("a").children("span.caret").first().hide();
ul.dropdown-menu:empty {
display: none;
}
<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.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<nav class="navbar navbar-default" role="navigation">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li class="dropdown">
Dropdown <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
</ul>
</li>
<li class="dropdown">
Contact Us <span class="caret"></span>
<ul class="dropdown-menu" role="menu"></ul>
</li>
</ul>
</nav>

Adding ng-click event with jQuery

Being new to Angularjs, I need a bit of help with this issue. I am attempting to add ng-click="getGallery(57)" to a modal tab. Adding via jQuery is not the issue, however I realize when I do this, Angular is not compiling the newly added ng-click. I have a simple controller
function imageGalleryCtrl ($scope, $http) {
//get gallery info on click
$scope.getGallery = function(id)
{
$http.post('/beta/images/get_images',{'id': id}).success(function(data)
{
$scope.images = data.thisGal_images;
$scope.images.galID = id;
});
};
}
I add the ng-click to the element with jQuery
//Edit image tab to use angularjs
$('#image_edit a').attr('ng-click','getGallery(' + settings.id + ')');
How do I force Angular to compile this newly added ng-click?
Thanks!
HTML Modal:
This is the modal that is called when the gallery name is clicked.
<div class="modal fade hide modal-creator" id="imageUploader" tabindex="-1" data-focus-on="input:first">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"></button>
<h3>Create New Gallery</h3>
</div>
<div class="modal-body">
<ul id="myTab" class="nav nav-tabs">
<li id="image_home" class="">
Home
</li>
<li id="image_upload" class="">
Upload Image Gallery
</li>
<li id="image_edit" class="">
Edit Image Gallery
</li>
</ul>
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade in" id="home">
<?php include('create.php'); ?>
</div>
<div class="tab-pane fade" id="upload">
<?php include('upload.php'); ?>
</div>
<div class="tab-pane fade" id="edit">
<div class="span9">
<ul id="imageSort" class="gallery-container">
<li ng-repeat="image in images">
<img ng-src="http://images.onlinealbumproofing.com/imageGallery/{{image.galleryID}}/{{image.imageName}}" alt="">
{{image.orgName}}
</li>
</ul>
</div><!-- /span9 -->
</div><!-- /row -->
</div>
</div>
</div><!-- /modal-body -->
<div class="modal-footer">
Close
Next
</div>
</div>
Update
So really attempting to do this the Angular way, and after some studies here is where I am at.
The controller is the same as above and I have updated the tabs on the modal as follows.
<div class="modal-body">
<ul id="myTab" class="nav nav-tabs">
<li id="image_home" class="">
Home
</li>
<li id="image_upload" class="">
Upload Image Gallery
</li>
<li id="image_edit" class="">
<a ng-click="getGallery(57)" href="#edit" data-toggle="tab">Edit Image Gallery</a>
</li>
</ul>
If I hard code the ng-click as above, the tab updates as expected. What I am trying to make happen, is when the modal is called, (#image_edit a) gets a defined ng-click="getGallery(id). I need to tell Angular to look at the ng-click again for the id.
Although I too think that you should try and find another approach, the answer to your question
How do I force Angular to compile this newly added ng-click?
is
// remove and reinsert the element to force angular
// to forget about the current element
$('#button1').replaceWith($('#button1'));
// change ng-click
$('#button1').attr('ng-click','exec2()');
// compile the element
$compile($('#button1'))($scope);
See this working example: http://plnkr.co/edit/SgvQzaY0TyFHD1Mf0c3F?p=preview
Basically what I'm getting at is you want to probably make this happen:
<ul id="imageSort" class="gallery-container">
<li ng-repeat="image in images">
<img
ng-src="http://images.onlinealbumproofing.com/imageGallery/{{image.galleryID}}/{{image.imageName}}"
alt=""
ng-click="getGallery(image.galleryID)"
>
{{image.orgName}}
</li>
</ul>
The problem is I'm unsure of the relationship between the settings.id and the galleryID for a particular image. If you can set up this relationship in the data so it just automatically binds you're in better shape.

Resources