AngularJs - Opening a Bootstrap dropdown menu on page load by programmatically triggering the "click" event (NO jQuery) - angularjs

May I ask if it's possible to trigger the click event of a dropdown menu programmatically on page load using AngularJS?
What I want to happen is that after loading the page, my navigation menu gets displayed automatically.
This is what I have so far:
<li class="menu-item" style="margin-top:15px">
<!-- Single button -->
<div class="btn-group open" uib-dropdown is-open="status.isopen">
<!-- Hamburger menu -->
<img ng-init="displayMainMenu()" id="nav-burger" uib-dropdown-toggle ng-disabled="disabled" ng-click="sMainMenu=true; isSubMenu=resetMenu(); getLinks(); bStopPropagation=true;" src="img/burger.png">
<!-- Main menu -->
<ul uib-dropdown-menu role="menu" aria-labelledby="single-button" ng-click="bStopPropagation && $event.stopPropagation()">
<!-- Main Menu -->
<li role="menuitem" class="main-menu-item" ng-repeat="link in links" ng-click="whatMenu(link.name); isSubMenu=false;" ng-show="isMainMenu">
<img id="{{link.icon}}">{{link.name}}<img class="navi-expand-icon">
</li>
<!-- End Main Menu -->
</ul>
</div>
</li>
And this is my Angular JS code:
$scope.displayMainMenu = function () {
var domElement = document.getElementById('nav-burger');
alert('before timeout'); // <-- This gets triggered
$timeout(function () {
angular.element(domElement).triggerHandler('click');
}, 0);
alert('after timeout'); // <-- This doesn't get triggered...
}
I have a feeling that I'm really close, however I couldn't figure out why it's not working.
Thank you in advance for your replies.

The ng-click on your image triggers this: ng-click="sMainMenu=true;"
However, to show your list items you have used isMainMenu ng-show="isMainMenu"
So I guess you made a typo.

Thank you for the clue Matheno! I did some more research about $timeout and finally got it to work by declaring $timeout in the controller:
app.controller('ctrlDropdown', function ($scope, $timeout) {
$scope.isMainMenu = true;
$scope.isSubMenu = false;
$scope.links = "";
$scope.subLinks = "";
$scope.selectedLink = "";
$scope.bStopPropagation = true;
...
}

Related

Angularjs: initiating first tab as active on page load

We are creating a tabs widget in ServiceNow and want to initiate the first tab as the active tab when the page loads. Right now when the page loads, this is what we see:
We actually want to see this on load:
Our code looks like this:
<ul class="nav nav-tabs">
<li ng-click="c.activateClass(tabs)" ng-repeat="tabs in c.data.tab_labels track by $index" ng-class="{'active':tabs.active}">
<a data-toggle="tab" href="#{{tabs}}">{{tabs}}</a>
</li>
</ul>
<div class="tab-content" >
<div ng-repeat="content in c.data.tab_labels" id="{{content}}" class="tab-pane fade in active">
<h3>{{content}}</h3>
<p>Some content.</p>
</div>
</div>
function($scope) {
/* widget controller */
var c = this;
c.data.tab_labels = c.options.tab_labels.split(',');
c.activateClass = function(subModule){
subModule.active = !subModule.active;
}
console.log('tabs');
console.log($scope);
}
We tried to use ng-init, but it was returning a console error. Any idea how to initiate the first tab on page load? Thanks!
You can set the active tab as active like this:
if(c.data.tab_labels.length > 0) {
c.data.tab_labels[0].active = true;
}
and show the active content:
<div ng-repeat="content in c.data.tab_labels | filter:{active:true}">

Submenu is not showing when applying dynamic menu using json angular

I am using a json file to show all the menus in my html page. I have applied menus in json file with right process. I am using angular to bind these menus to html page. All the main menus are displaying there. But the issue is when i click on submenu arrow, it is showing blank. Also only one menu item has submenu that is about us menu, but it is showing counter 1 to each menu item. The url to see how it is looking is dynamic menu using json angular
How to apply those submenu to only about us menu and how to display submenus when clicked on about us menu ?
my html code is
<nav id="menu" ng-app="demoApp" ng-controller="demoCtrl">
<ul id="my-list">
<li ng-repeat="menu in menus">
<a href="{{menu.url}}">
{{menu.name}}
</a>
<ul ng-show="menu.sub.length!=0">
<li ng-repeat="subItem in menu.sub">
{{subItem.name}}
</li>
</ul>
</li>
</ul>
</nav>
Rest of the source you can find in given url.
Demo link working
In your code the menu script loaded before your angular so the sub data not loaded properly.
change your code like this. set timeout for your script
Changes done Here:-
$(function() {
setTimeout(function(){
$("#menu").mmenu({
extensions : ["widescreen"],
counters : true,
navbars : [{
content: ["searchfield"]
}, true]
}).on( 'click',
'a[href^="#/"]',
function() {
alert( "Thank you for clicking, but that's a demo link." );
return false;
}
);
var API = $("#menu").data( "mmenu" );
}, 3000);
});

Bootstrap 3: Deselect tab using angular js

I'm working with angular js and bootstrap 3 and my app works like ... I have a view where you have several links which let you show a div with several tabs and select one of them. This works fine. But if I change the tab through a click over it and then I hide the view with the tabs when I make click on another click I show the view with the tabs, with the tab selected from the link, that's correct, but ... with the previous tab clicked.
So, how I can deselect the tab where I have been make click over it?
Edit 1:
I'm going to post several screenshots to try to explain better my problem.
Edit 2:
I add this plunker to show how it works my code and you can check that if you clic on a tab, if later returns clicking a button you don't select the correct tab. https://plnkr.co/edit/y22T01OwxgttDWM1mJeH
HTML:
<body ng-controller="MainCtrl as ctrl">
<button id="bTab1" ng-click="ctrl.buttonClicked($event)">
Tab 1
</button>
<button id="bTab2" ng-click="ctrl.buttonClicked($event)">
Tab 2
</button>
<button id="bTab3" ng-click="ctrl.buttonClicked($event)">
Tab 3
</button>
<div ng-show = "ctrl.show_tabs">
<div class = "row" style = "text-align: right; margin-top: 10px">
<button ng-click="ctrl.closeTab()">
Hide Tabs
</button>
</div>
<ul class="nav nav-tabs" id="myTab">
<li ng-class = "ctrl.active_pai"><a data-target="#pai" data-toggle="tab">PAI</a></li>
<li ng-class = "ctrl.active_pap"><a data-target="#pap" data-toggle="tab">PAP</a></li>
<li ng-class = "ctrl.active_ip"><a data-target="#ip" data-toggle="tab">IP</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane" ng-class = "ctrl.active_pai" id="pai">Content PAI</div>
<div class="tab-pane" ng-class = "ctrl.active_pap" id="pap">Content PAP</div>
<div class="tab-pane" ng-class = "ctrl.active_ip" id="ip">Content IP</div>
</div>
</div>
</body>
Javascript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var self = this;
$scope.name = 'World';
self.show_tabs = false;
self.active_pai = "";
self.active_pap = "";
self.active_ip = "";
self.buttonClicked = function(event) {
self.show_tabs = true;
if (event.currentTarget.id == "bTab1"){
self.active_pai = "active";
self.active_pap = "";
self.active_ip = "";
}
if (event.currentTarget.id == "bTab2"){
self.active_pai = "";
self.active_pap = "active";
self.active_ip = "";
}
if (event.currentTarget.id == "bTab3"){
self.active_pai = "";
self.active_pap = "";
self.active_ip = "active";
}
};
self.closeTab = function(){
self.show_tabs = false;
}
});
Edit 3:
More problems:
In my code, I've got tabs and Bootstrap calendar and with the given solution works fine without bootstrap calendar, but If add bootstrap calendar, this doesn't work correctly.
I have modified my origina plunker and I have added a bootstrap calendar and change these libraries:
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap-tpls.min.js"></script>
By these:
<script type="text/javascript" src="bootstrap.min.js"></script>
<script type="text/javascript" src="ui-bootstrap-tpls-0.14.3.min.js"></script>
The code of these libraries you've got on the plunker. Plus I have added the controller which manage the bootstrap calendar.
Ok, If we go to the plunker: https://plnkr.co/edit/PaSqa0jxQjz48pzcmBMa
We can see that we have a bootstrap calendar where I cannot select day greater than today + 1. That's correct! But, If I make a click on button "Tab 2", the Tab that we can see is not 2, it's 1. If I do the same with tab 3, I've got the same result. That's wrong. The correct functionality is If I make a click on button "Tab 2", we can see tab 2, for example.
Ok, If I change on the plunker these libraries ...
<script type="text/javascript" src="bootstrap.min.js"></script>
<script type="text/javascript" src="ui-bootstrap-tpls-0.14.3.min.js"></script>
By the given in the solution:
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap-tpls.min.js"></script>
We can see that the tabs works correctly, but bootstrap calendar lets you to select days greater than today + 1. And this is wrong!
I would recommend using angular-ui-bootstrap tabs for this. It provides angular wrappers around most of the bootstrap functionality (mostly directives), so it makes these types of things much easier to write (and code is cleaner, as you'll see below). I modified your plunkr as minimally as possible, but changed it to make use of the ui-bootstrap tabs: https://plnkr.co/edit/qqvY2acsZWbkyFCCT7qr?p=info
New Controller:
app.controller('MainCtrl', function($scope) {
var self = this;
$scope.name = 'World';
self.buttonClicked = function(index) {
self.show_tabs = true;
self.active = index;
};
self.closeTab = function(){
self.show_tabs = false;
}
});
Html changes:
<button id="bTab1" ng-click="ctrl.buttonClicked(1)">
Tab 1
</button>
<button id="bTab2" ng-click="ctrl.buttonClicked(2)">
Tab 2
</button>
<button id="bTab3" ng-click="ctrl.buttonClicked(3)">
Tab 3
</button>
...
<div ng-show = "ctrl.show_tabs">
...
<uib-tabset active="ctrl.active">
<uib-tab index="1" heading="PAI">Content PAI</uib-tab>
<uib-tab index="2" heading="PAP">Content PAP</uib-tab>
<uib-tab index="3" heading="IP">Content IP</uib-tab>
</uib-tabset>
</div>
ctrl.active, which is passed into the active attribute on <uib-tabset> just represents the index of the currently opened tab, so just changing its value will change which tab is open/visible. There are some more attributes that can be used for these directives (you can see them on the page I linked to above), but this shows the basis of how these tab directives can be used. I haven't seen the issue you were describing above after these changes.

How to set bootstrap active tab on refresh in Angular JS

I am creating tabs as:
<tabset class="content-tabset no-margin">
<tab ng-repeat="t in t.values" heading="{{t.name}}" active="t.active">
//other stuff
</tab>
</tabset>
Now within this other stuff I also have button which when clicks updates the row and refreshes that part. When the refresh happens it also resets the tab I am currently on.
So if I am tab two and click on the button, the panel refreshes and I come back on tab 1. How can I prevent this?
Use localStorage. Set it on selecting tab. To get boolean value of active state for current tab use ng-init.
<tabset class="content-tabset no-margin">
<tab
ng-repeat="t in t.values"
heading="{{t.name}}"
ng-init="isActive = isActiveTab(t.name, $index)"
active="isActive"
select="setActiveTab(t.name)">
//other stuff
</tab>
</tabset>
And in your controller
$scope.setActiveTab = function( activeTab ){
localStorage.setItem("activeTab", activeTab);
};
$scope.getActiveTab = function(){
return localStorage.getItem("activeTab");
};
$scope.isActiveTab = function( tabName, index ){
var activeTab = $scope.getActiveTab();
return ( activeTab === tabName || ( activeTab === null && $index === 0 ) );
};
NOTE: Since your t has no unique ID for tabs, names should be unique to detect active tab correctly.
See example JSFiddle.
Whenever you do a refresh the local/scope variables runs out of scope. So the way out to solve this is using JavaScript's Session Storage/ Local Storage.
Session storage will run out of scope once you close the browser while local storage will persist value till window and browser lifetimes.
Inside controller:
$scope.selTab = sessionStorage.tabName; //On refresh it will fetch value from session storage
$scope.onClickTab = function(tabName){ //On click it will set the sessionStorage
$scope.selTab = tabName;
sessionStorage.tabName = tabName;
}
Inside HTML must refer your controller
<ul class="nav nav-pills col-md-12 col-sm-12 col-xs-12{{active}}">
<li ng-class ="{active:selTab=='tab1'}">Tab3</li>
<li ng-class ="{active:selTab=='tab3'}">Tab3</li>
</ul>
You can use this package ui-router-tabs. Follow the link https://github.com/rpocklin/ui-router-tabs. Easy to use and gets the job done.
I have solved it by using Local Storage
Inside HTML:
<ul class="nav">
<li>
<a ng-click="goToManageUsers('manageUser')" ng-class="{'active': selectedTab == 'manageUser'}">
<i class="lnr lnr-home"></i>
<span>Manage User</span>
</a>
</li>
<li>
<a ng-click="goToManageRequest('manageImage')" ng-class="{'active': selectedTab == 'manageImage'}">
<i class="lnr lnr-home"></i>
<span>Manage Image</span>
</a>
</li>
</ul>
Inside Controller:
$scope.selectedTab = localStorage.getItem('getActive');
$scope.goToManageUsers = function (user) {
$scope.selectedTab = user;
localStorage.setItem('getActive', user);
}
$scope.goToManageRequest = function (image) {
$scope.selectedTab = image;
localStorage.setItem('getActive', image);
}
To do this same thing in Angular 2+, you also use LocalStorage. Something like this (I used ng-bootstrap to enable Bootstrap tabs):
HTML:
<ngb-tabset class="nav-fill" (tabChange)="tabChange($event)" [activeId]="activeTabId">
<ngb-tab title="Tab 1" id="tab1">
...
</ngb-tab>
<ngb-tab title="Tab 2" id="tab2">
...
</ngb-tab>
</ngb-tabset>
.ts:
import {NgbTabChangeEvent} from "#ng-bootstrap/ng-bootstrap";
... other imports
export class MyComponent {
activeTabId: string;
constructor() {
this.activeTabId = localStorage.getItem("activeTab");
}
tabChange($event: NgbTabChangeEvent) {
localStorage.setItem("activeTab", $event.nextId);
}
}

Angularjs: Call bootstrap modal multiple views.

My goal is to move the modal out of my source view, and move it into its own view, but for some reason, my modal does not show up. I have tried putting the modal into a directive, but its not working. I have moved the modal to the index page, but then the view changes when they modal opens.
Category.html
<section class="row">
<h1>{{ selectedCategory | uppercase}}</h1>
<div class="col-md-3 col-xs-12" ng-repeat="source in sources[selectedCategory]">
<a ng-href="#/explore/{{selectedCategory}}/{{source.name}}">
<section class="col-xs-2">
<img ng-src="assets/img/{{source.imagename}}" height="30" width="30">
</section>
<p class="col-xs-8">{{ source.name }}</p>
</a>
<div ng-if="!objectContains(addedSources,source.name)"><!-- Show this, if addesSources does not contains source.name -->
<section class="col-xs-2">
<!-- This part, is where i want the modal to be called. -->
<button class="tiny" data-toggle="modal" data-target="#myModal" ng-click="setUpModalData(source.name)">Add</button>
</section>
</div>
<div ng-if="objectContains(addedSources,source.name)"> <!-- Show this, if addesSources contains source.name -->
<section class="col-xs-2">
<button class="tiny secondary" ng-click="removeSource(source.name)">remove</button>
</section>
</div>
</div>
</section>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal content -->
</div><!-- modal-content -->
</div><!-- modal-dialog -->
</div><!-- myModal -->
Currently the controller does not open or close the modal, its only job is to provide the information shown in the modal. If you click on add for a particular source, the modal will open with that source name on the top.
I have tried doing what seems to work for other people, but i cant get it to work for me.
I want to be able to call this modal from different views. You can click add on the source List view (list of all sources), and the individual source view(details about one source). There will be an add button on both views, that will both call this modal.
I am using twitter bootstrap for the css.
Here is my Controller for this view.
.controller('CategoryController', ['$scope', '$http', '$routeParams', function($scope, $http, $routeParams){
$http.get('assets/js/Category.json').success(function(data) {
$scope.selectedCategory = $routeParams.simplename; //Get the the name of the url
$scope.sources = data; //set sources list, for view to iterate.
$scope.collectionList = {}; // List of all collections, and source under every collection
$scope.addedSources = {}; // object of sources, and the collection they're in. etc ("The Verge" : tech)
$scope.setUpModalData = function(simplename){
$scope.selectedSourceName = $scope.selectedSourceNameTitle =simplename;
$scope.selectedCollection = $scope.selectedCategory;
/* if the current category does not exist in the collection list,
* we will pre fill the form with the current category.
* Other wise we will set it, and it will not be pre pubulated.
*/
if(!($scope.selectedCategory in $scope.collectionList)){
$scope.collectionName = $scope.selectedCategory;
$scope.selectedCollection = 'createNewCollection';
}
}
$scope.removeSource = function(simplename){
var collectionNameHolder = $scope.addedSources[simplename]; //The collection the source is in.
delete $scope.collectionList[collectionNameHolder][simplename]; //delete the source from both lists.
delete $scope.addedSources[simplename]
}
$scope.arrayContains = function(array, element){
return (array.indexOf(element) > -1);
}
$scope.objectContains = function(object, element){
return (element in object);
}
});
}])
Can you put that in a simplified jsfiddle? I'm not sure about what you're trying to achieve and what's not working.
In any case, if you want to have a single modal for multiple views, you could do that with a service, which job would be to open or close the modal, or with events on rootScope which would tell the modal's controller that the modal should be displayed or hidden.
https://docs.angularjs.org/guide/services#creating-services
https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast

Resources