How to change clicked item glyphicon - angularjs

am binding list of products from database in my page with icon,
initially am showing glyphicon off for all items , when i click list item am changing clicked item glyphicon to ok,
but if i select any other item in list first item glyphicon changing to ok , i want to change icon of clicked item
my code is
view
<div class="collapse navbar-collapse " id="myNavbar">
<ul class="nav navbar-nav">
<li ng-repeat="prod in products">
{{prod.PRODCTNAME}}<span id="iProduct" class="glyphicon glyphicon-off ChangeButtonColorOrangeRed"></span>
</li>
</ul>
</div>
js
$scope.getModules = function (event) {
var prodID = event.target.id;
var productElement = angular.element(document.querySelector('#iProduct'));
productElement.toggleClass('glyphicon glyphicon-off ChangeButtonColorOrangeRed').toggleClass('glyphicon glyphicon-ok ChangeButtonColorGreen');
var moduleDiv = angular.element(document.querySelector('#divModule'));
moduleDiv.toggleClass('divProductsHide').toggleClass('divProductsShow');
productService.getModules(prodID).then(function (d) {
$scope.modules = d.data;
}, function (error) {
alert('Error!');
});
};
css
<style>
.ChangeButtonColorOrangeRed {
color: orangered;
}
.ChangeButtonColorGreen {
color: green;
}

You can also get selected Item by using this example below.Plunker here
HTML
<body data-ng-controller="myController">
<div class="collapse navbar-collapse " id="myNavbar">
<ul class="nav navbar-nav">
<li ng-repeat="prod in products">
<a href="#" class="productClass" ng-click="selectProduct(prod.id)">{{prod.name}}
<span data-ng-hide="selectedProducts.indexOf(prod.id) > -1" class="glyphicon glyphicon-off ChangeButtonColorOrangeRed"></span>
<span data-ng-show="selectedProducts.indexOf(prod.id) > -1" class="glyphicon glyphicon-ok ChangeButtonColorGreen"></span>
</a>
</li>
</ul>
</div>
</body>
JS
angular.module("myApp",[]);
angular.module("myApp").controller("myController",function($scope){
$scope.products = [
{id:1,name:'A'},
{id:2,name:'B'},
{id:3,name:'C'}
];
$scope.selectedProducts = [];
$scope.selectProduct = function(id){
var index = $scope.selectedProducts.indexOf(id);
if(index > -1){
$scope.selectedProducts.splice(index,1);
}else{
$scope.selectedProducts.push(id);
}
}
})
Update
Change this function for selecting only one product
$scope.selectProduct = function(id){
$scope.selectedProducts= [id];
}

You can use ng-class to solve this problem.
<div class="collapse navbar-collapse " id="myNavbar">
<ul class="nav navbar-nav">
<li ng-repeat="prod in products" ng-init="off=false">
{{prod.PRODCTNAME}}<span id="iProduct" ng-class="off?'change-button-to-green':'change-button-to-red'"></span>
</li>
</ul>
</div>
CSS:
.change-button-to-red {
color: orangered;
}
.change-button-to-green {
color: green;
}
This will solve problem.

Issue is in selection:
var productElement = angular.element(document.querySelector('#iProduct'));
You are selecting value with id '#iProduct'. So query selector pick the first match and change the class of the first span.
So, provide dynamic id to span also.
I added a fiddle for this:
https://jsfiddle.net/ranageneration/s5ua3fed/

Related

selecting element in uib-dropdown menu

I Have a HTML code like this.
<div ng-if="!hide" class="dropdown pull-right" uib-dropdown>
<a uib-dropdown-toggle href="" >
<div class="btn btn-primary-outline btn-circle btn-xs pull-right comment-button">
<span class="icon icon-chevron-down"></span>
</div>
</a>
<ul class="dropdown-menu " style="text-align: center;" role="menu" uib-dropdown-menu>
<li role="divider" ng-if="showDelete">delete </li>
<li role="divider"> report</li>
</ul>
</div>
When using in protractor facing an issue with uib-dropdown selection.
I written code like this:
var dropDown = element(by.css("div[uib-dropdown]"));
dropDown.element(by.css("a[uib-dropdown-toggle]"));
dropDown.element(by.css("a[ng-click=deleteItem($index)]")).click();
browser.sleep(5000);
this.selectMenuOption = function (option) { //menu item to click
var dropdown = element(by.className('dropdown pull-right'));
dropdown.click();
dropdown.element(by.tagName('ul')).all(by.tagName('li')).filter(function (elem) {
return elem.getText().then(function (val) {
return val.toUpperCase() === option.toUpperCase();
})
}).first().click();
}
The a[ng-click=deleteItem($index)] is actually an invalid CSS selector, you needed to put the attribute value into quotes:
dropDown.element(by.css('a[ng-click="deleteItem($index)"]')).click();
Though, I'd go for a partial match that appears to be more readable:
dropDown.element(by.css('a[ng-click*=deleteItem]')).click();
where *= means "contains".
Or, you can even go for a "link text" locator:
dropDown.element(by.linkText('delete')).click();
dropDown.element(by.partialLinkText('delete')).click();

Can I set `ng-repeat` object as `model` to share the details?

I am using ng-repeat to display a property of an array. and i need further details to share with other elements to from this array. but the element not nested inside of the ng-repeat.
In this case is it possible to set the array object as a model to share the details to other elements?
here is my code :
<ul>
<li ng-click="activate(item)" ng-model="item" ng-repeat="item in items" ng-class="{active : active == item}">
<span ng-if="item == active">
<span>{{item.name}}</span>
<!-- when active nested under span -->
</span>
<!-- else without nesting the span -->
<span ng-if="item !== active">{{item.name}}</span>
</li>
</ul>
<h1>{{item.age}}</h1> //i am trying to fetch model info here
You can make ng-click set the item to a scope variable:
var app = angular.module('app', []);
app.controller('myController', function($scope) {
$scope.items = [{
name: 'a',
age: 12
}, {
name: 'b',
age: 15
}];
$scope.activate = function(item) {
$scope.active = item;
};
});
.active {
color: green;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app='app' ng-controller='myController'>
<ul>
<li ng-click="activate(item)" ng-repeat="item in items" ng-class="{active : active == item}">
<span ng-if="item == active">
<span>{{item.name}}</span>
<!-- when active nested under span -->
</span>
<!-- else without nesting the span -->
<span ng-if="item !== active">{{item.name}}</span>
</li>
</ul>
<h1>{{active.age}}</h1>
</div>

Angular how to redirect to a tab

I have a page which has got 5 tabs. There is another page which contains the links pointing to these tabs. Whenever a user clicks a link on this page, corresponding tab should be opened on angular application page.
The tab are working fine when user manunally clicks on a tab but I am unable to find how can I select a tab by default.
Add in app.js:
$routeProvider.when('/trend', {
templateUrl:'partials/trend.html'
}).when('/deepdive', {
templateUrl:'partials/deepdive.html'
}).when('/driversNdrainers', {
templateUrl:'partials/DriversNDrainers.html'
}).when('/timeline', {
templateUrl:'partials/timeline.html'
}).otherwise("/trend");
index page:
<div header></div>
<div class="row">
<div class = "col-md-12" ng-include="'partials/home.html'"></div>
</div>
<div footer></div>
The home controller creates the tabs dynamically.
Home.html
<div class="" fade-in ng-controller="HomeCtrl">
<ul class="nav nav-pills">
<li ng-class="tabClass(tab)" ng-repeat="tab in tabs" tab="tab"><a href="{{tab.link}}" id="{{tab.id}}"
ng-click="setSelectedTab(tab)">{{tab.label}}</a></li>
</ul>
<div ng-view></div>`enter code here`
Controller:
var homectrl = myApp.controller('HomeCtrl', ['$scope', '$routeParams', '$location','$state', function ($scope, $routeParams,$location,$state) {
$scope.tabs = [
{ link : '#/trend', label : 'Trend', id: "trendLink"},
{ link : '#/deepdive', label : 'Deep Dive' , id:"deepdriveLink"},
{ link : '#/driversNdrainers', label : 'Drivers & Drainers', id:"ddLink" },
{ link : '#/timeline', label : 'Timeline' , id: "timelineLink"},
{ link : '#/zoomin', label : 'Zoom In', id: "zoominLink" }
];
$scope.selectedTab = $scope.tabs[0];
$scope.setSelectedTab = function(tab) {
$scope.selectedTab = tab;
};
$scope.tabClass = function(tab) {
return $scope.selectedTab == tab? "active": "";
};
angular.element(document).ready(function () {
$.each($scope.tabs,function(i){
if(this.link==location.hash){
$scope.setSelectedTab(this);
//$state.go("/trend");
return;
}
});
});
}]);
What I see here is that the tab is selected but the content inside tab is not loaded.
Your code inside jQuery is not executed in Angular's digest cycle. Try adding $scope.$apply(); right after $scope.setSelectedTab(this);
To understand why you should do this read: "Scope Life Cycle" at https://docs.angularjs.org/guide/scope
Here is the solution you can refer to stackblitz
I had to do some modification in its function to achieve the result as per my requirement.
modified solution:
moveToSelectedTab(tabName: string) {
for (let i = 0; i < document.querySelectorAll('[aria-selected]').length; i++) {
let element = document.querySelectorAll('[aria-selected="false"]')[i];
if (element != undefined) {
if ((<HTMLElement>document.querySelectorAll('[aria-selected="false"]')[i]).innerHTML == tabName) {
(<HTMLElement>document.querySelectorAll('[aria-selected="false"]')[i]).click();
}
}
}}
HTML
<ul class="nav nav-tabs" id="editorTab" role="tablist">
<li class="nav-item active" role="presentation">
<a class="nav-link active" id="bannerArea-tab" data-toggle="tab" href="#bannerArea" role="tab"
aria-controls="bannerArea" aria-selected="true">General Information</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="cardArea-tab" data-toggle="tab" href="#cardArea" role="tab"
aria-controls="cardArea" aria-selected="false">Banner Content</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="mainArea-tab" data-toggle="tab" href="#mainArea" role="tab"
aria-controls="mainArea" aria-selected="false">Main Content</a>
</li>
</ul>
<div class="tab-content" id="editorTabContent">
<div class="tab-pane fade show active col-sm-12" id="bannerArea" role="tabpanel" aria-labelledby="bannerArea-tab">
<div class="form-group">
</div>
<div class="text-right margin-top-xl">
<button class="btn-icon-confirm" (click)="moveToSelectedTab('Banner Content')">Next<i class="material-icons">arrow_forward</i></button>
</div>
</div>
<div class="tab-pane fade show active col-sm-12" id="cardArea" role="tabpanel" aria-labelledby="cardArea-tab">
<div class="form-group">
</div>
<div class="text-right margin-top-xl">
<button class="btn-icon-confirm" (click)="moveToSelectedTab('Main Content')">Next<i class="material-icons">arrow_forward</i></button>
</div>
</div>
<div class="tab-pane fade col-sm-12" id="mainArea" role="tabpanel" aria-labelledby="mainArea-tab">
<div class="text-right margin-top-xl">
<button class="btn-icon-confirm" (click)="moveToSelectedTab('General Information')"><i class="material-icons">check</i></button>
</div>
</div>
</div>

Show and hide elements of ng-repeat cycle

Here is my HTML:
<ul class="no-bullet">
<li ng-repeat="(group, count) in info.info">
<a href="#" ng-click="getQuestions(group)"
ng-mouseenter="showGroupPanel()" ng-mouseleave="hideGroupPanel()"
>{{group}} ({{count}}) </a>
<div class="group_panel" ng-show="hoveringGroup">
<i class="fa fa-check"></i>
<i class="fa fa-folder-o"></i>
</div>
</li>
And here is my JS:
$scope.hoveringGroup = false;
$scope.showGroupPanel = function() {
$scope.hoveringGroup = true;
}
$scope.hideGroupPanel = function() {
$scope.hoveringGroup = false;
}
When user mouseover one of elements of the list additional div (group_panel) is displayed. But it is displayed for all elements of the list. How can I fix it to display "group-panel" div only for one element (mouseovered) of the list?
Simplest way : use ng-repeat's isolate scope. (hoveringGroup will be a separate variable for each ng-repeat iteration)
<ul class="no-bullet">
<li ng-repeat="(group, count) in info.info">
<a href="#" ng-click="getQuestions(group)"
ng-mouseenter="hoveringGroup = true" ng-mouseleave="hoveringGroup = false"
>{{group}} ({{count}}) </a>
<div class="group_panel" ng-show="hoveringGroup">
<i class="fa fa-check"></i>
<i class="fa fa-folder-o"></i>
</div>
</li>
You could also store the information in your repeated item :
<ul class="no-bullet">
<li ng-repeat="info in info.info">
<a href="#" ng-click="getQuestions(info.group)"
ng-mouseenter="showGroupPanel(info)" ng-mouseleave="hideGroupPanel(info)"
>{{info.group}} ({{info.count}}) </a>
<div class="group_panel" ng-show="info.hoveringGroup">
<i class="fa fa-check"></i>
<i class="fa fa-folder-o"></i>
</div>
</li>
$scope.showGroupPanel = function(info) {
info.hoveringGroup = true;
}
$scope.hideGroupPanel = function(info) {
info.hoveringGroup = false;
}
var app = angular.module('app', []);
app.controller('homeCtrl', function($scope) {
$scope.info = {
info: [{
id: 1
}, {
id: 2
}, {
id: 3
}
]
}
$scope.hoveringGroup = false;
$scope.showGroupPanel = function(level) {
level.hoveringGroup = true;
}
$scope.hideGroupPanel = function(level) {
level.hoveringGroup = false;
}
$scope.createlevel = function(count, level) {
return angular.copy(count, level)
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
<div ng-app="app">
<div ng-controller="homeCtrl">
<ul class="no-bullet">
<li ng-repeat="(group, count) in info.info" ng-init="level =createlevel(count,level)">
{{group}} ({{count}})
<div class="group_panel" ng-show="level.hoveringGroup">
<i class="fa fa-check"></i>
<i class="fa fa-folder-o"></i>
</div>
</li>
</ul>
</div>
</div>

How can I add a class on click with AngularJS and Angular Bootstrap/UI?

I'm fighting against my own grain on this, trying to learn.
I have a Bootstrap menu... Here's part of it:
<div id="language_menu" class="dropdown" on-toggle="toggled(open)">
<a class="dropdown-toggle" ng-model="clicked"> <span class="flag-xs flag-us"></span> <span class="small va-m">US</span> <i class="fa fa-angle-down"></i> </a>
<ul class="dropdown-menu">
<li><span class="flag-xs flag-in"></span> Hindu</li>
<li><span class="flag-xs flag-tr"></span> Turkish</li>
<li><span class="flag-xs flag-es"></span> Spanish</li>
</ul>
</div>
Here's the part of my controller in question:
$scope.toggled = function(open) {
if (open) {
$('#language_menu').find('.dropdown-menu').addClass('animated-shortest animated flipInX');
} else {
$('#language_menu').find('.dropdown-menu').removeClass('animated-shortest animated flipInX');
}
};
I'm confused as to the best method for this. ngClick vs dealing with it on the controller in the toggled function? You can see what I'm trying to achieve just by the jQuery. I know this is wrong, or maybe I'm skipping the angular way of handling it...
Please excuse me as I'm entirely new to Angular.
---- Update ----
Would it be considered improper to handle it this way?
<div id="language_menu" class="dropdown" on-toggle="toggled(open)" >
<a class="dropdown-toggle" href="#"> <span class="flag-xs flag-us"></span> <span class="small va-m">US</span> <i class="fa fa-angle-down"></i> </a>
<ul class="dropdown-menu {{theClass}}">
<li><span class="flag-xs flag-in"></span> Hindu</li>
<li><span class="flag-xs flag-tr"></span> Turkish</li>
<li><span class="flag-xs flag-es"></span> Spanish</li>
</ul>
</div>
$scope.toggled = function(open) {
if (open) {
$scope.theClass = 'animated-shortest animated flipInX';
} else {
$scope.theClass = '';
}
};
ngClass will help. Here's a working example: http://jsfiddle.net/tgg4eq4j/
Some code:
HTML:
<div ng-app="TestApp" ng-controller="TestCtrl">
<button ng-click="toggle()">Toggle</button>
<span ng-class="getClass()">I'm toggled</span>
</div>
And the JS:
var app = angular.module("TestApp", []);
app.controller("TestCtrl", ["$scope", function ($scope) {
var flag = true;
$scope.getClass = function () {
return flag ? "whitesmoke": "white";
}
$scope.toggle = function () {
flag = !flag;
};
$scope.class = "whitesmoke";
}]);
Use ngClass:
<div id="language_menu" ng-class="{'animated-shortest animated flipInX': open}" on-toggle="toggled(open)">
</div>

Resources