On click adding and removing classes in angularJs - angularjs

I want to remove active class from an li and add it to another li.
I know how to do it with jQuery but I don't know how to make it work with AngularJS.
Here is my code :
$(document).ready(function() {
// event to nav bar header
$("ul.nav li").click(function() {
$("ul.nav li").removeClass("active");
$(this).addClass("active");
});
});
Demo Here

You can build up an array of your nav items in your scope and call a function which sets a variable to true if the respective string matches.
Furthermore, I suggest building your nav with ng-repeat based on this very array.
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
var navArr = [
'home',
'help',
'admin'
];
$scope.setNavActive = function(str) {
console.log(str);
angular.forEach(navArr, function(item) {
console.log(item);
$scope[item] = (str == item);
});
};
$scope.home = true;
}
.nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {
color: #fff;
background-color: #6da54d;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<ul class="nav nav-pills pull-right mynavbar">
<li ng-class="{active: home}" ng-click="setNavActive('home')"><a ng-href="#/">Home</a></li>
<li ng-class="{active: help}" ng-click="setNavActive('help')"><a ng-href="#/help">Help</a></li>
<li ng-class="{active: admin}" ng-click="setNavActive('admin')"><a ng-href="#/administration">Administration</a></li>
</ul>
</div>

I like to use the ternary operator
ng-class="(clickedBoolean) ? 'active' : ''"
Just change clickedBoolean to whatever your click event is changing and your ng-class directive will act accordingly.

Related

angularjs pass index through directive

I need help with this code.
<ul ng-init="round = 'round'">
<li ng-repeat="mesa in mesas" ng-click="selected($index)">
<div id="{{round}}"> </div>
MESA {{mesa}}
</li>
</ul>
$scope.selected = function ($index){
$scope.index.round = 'round1';
}
I need that only the li that is being clicked to change the css name, but instead it change all of the li's that I have listed.
You're initializing the variable round outside of the repeat loop, so the expression {{round}} will always point to that singular, shared variable. If you update it once, it updates for all children of the ng-repeat.
If I understand your question, you're trying to change the CSS class for the div inside the repeat, correct? What you can do in that case is store the selected index on the controller's scope, and check that value against the index inside the loop
<ul>
<li ng-repeat="mesa in mesas" ng-click="select($index)">
<div class="round1" ng-if="selectedIndex === $index"> </div>
<div class="round" ng-if="selectedIndex !== $index"> </div>
MESA {{mesa}}
</li>
</ul>
$scope.select = function ($index){
$scope.selectedIndex = $index;
}
You could also use ng-class instead of ng-if depending on how your CSS is structured, but the idea is the same.
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<style type="text/css">
.round {
background: green;
}
.round1 {
background: blue;
}
</style>
</head>
<body ng-controller="controller">
<ul>
<li ng-repeat="mesa in mesas" ng-click="selected($index)" ng-class="[index[$index].round]">
<div id="{{ index[$index].id }}"> </div>
MESA {{ mesa }}
</li>
</ul>
</html>
<script type="text/javascript">
angular.module('app', [])
.controller('controller', controller);
controller.$inject = ['$scope'];
function controller($scope) {
$scope.mesas = ['1', '2', '3'];
$scope.index = [{
id: '1',
round: 'round'
}, {
id: '2',
round: 'round'
}, {
id: '3',
round: 'round'
}];
$scope.selected = function($index) {
$scope.index[$index].round = $scope.index[$index].round === 'round' ? 'round1' : 'round';
}
}
</script>
I think is what u looking for¿?

add/remove class of multiple li in angularjs

I have list as below...
<ul id="menu">
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
Now, when a particular li is clicked, I want the active class to be added to the same and remove active class from the rest of the li elements. Also, when the same li is clicked again I want to remove active class.
How, can i do this using ng-click and ng-class?
Check the below example:
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', ['$scope', function($scope) {
$scope.setMaster = function(section) {
$scope.selected = section;
}
$scope.isSelected = function(section) {
return $scope.selected === section;
}
}]);
.active {
background-color: orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<ul>
<li ng-repeat="i in ['One', 'Two', 'Three']" ng-class="{active : isSelected(i)}">
<a ng-click="setMaster(i)">{{i}}</a>
</li>
</ul>
<hr> {{selected}}
</div>

Improve Angular Tabs directive

I created an angular tab directive width JQuery.
I can't find the problem with it because all seems right.
Could someone check what am I doing wrong?
I think my Angular directive is to dependent of jQuery.
What steps should I take to make it more "Angular"?
angular.module('app', []);
angular.module("app").directive("tabs", function() {
return {
restrict: "A",
link: function(scope, element, attributes) {
var tabs = element.find("a");
var sections = links.map(function() {
return $("#" + this.href.split("#")[1])
});
$(tabs[0]).show();
sections[0].show();
tabs.bind("click", function(event) {
event.preventDefault();
tabs.not(this).hide();
$(this).siblings("a").hide();
$.each(sections, function() {
$(this).hide()
});
$("#" + this.href.split("#")[1]).show();
});
}
};
});
ul.tabs {
list-style: none;
margin: 0;
padding: 0;
}
ul.tabs li {
display: inline-block;
margin: 0;
padding: 0;
}
ul.tabs li a {
text-decoration: none;
color: white;
padding: 8px;
display: block;
background-color: indigo;
}
div.section {
background-color: #f0f0f0;
padding: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<ul class="tabs">
<li>Tab 1
</li>
<li>Tab 2
</li>
</ul>
<div id="section1" class="section">Section 1</div>
<div id="section2" class="section">Section 2</div>
I'm not going to try fixing your code. Just explain how you would do this the Angular way.
jQuery is all about DOM manipulation. In Angular, DOM manipulation is bad. The DOM should automatically adapt itself based on the model. Tabs can simply be implemented the following way:
<ul class="tabs">
<li><a href ng-click="selectedTab = 1">Tab 1</a>
</li>
<li><a href ng-click="selectedTab = 2">Tab 2</a>
</li>
</ul>
<div class="section" ng-show="selectedTab === 1">Section 1</div>
<div class="section" ng-show="selectedTab === 2">Section 2</div>
This is much simpler: clicking on a tab changes the value of the selectedTab model value. The sections hide/show themselves based on the value of selectedTab.
Can be something like:
angular.module("app").directive("tabs", function() {
return {
restrict: "A",
scope: {
tabs: '='
},
template : '<ul><li ng-repeat="section in tabs" ng-click="handleClick(section)" ng-class="{selected : section.selected}">{{section.name}}</li></ul>',
link: function(scope, element, attributes) {
scope.handleClick = function(section) {
//....
}
}
};
});
where tabs is array like [{name : 'N1', href : '#smth', selected: false}, ...] in html:
<div tabs="tabs"></div>
You can add selected property, disabled, etc. Also notice - that if you change tabs array - template will redraw itself automatically.

Want to make the li elements of ul list visible but not clickable using angularjs

I have a small issue regarding how to make the 'li' elements of 'ul' list visible but not-clickable. I tried using ng-disabled directive to disable it i.e., not-clickable but it doesn't seem to work. Could please help me out in this issue which would be highly appreciable.
Code Example (Plunker Link)
If you just want to prevent click events from registering on your li's, you could implement this CSS rule:
li { pointer-events: none; }
If you need this to be dynamically set from Angular, consider using the core ngClass directive:
CSS:
.no-click { pointer-events: none; }
HTML:
<li ng-class="{'no-click': clickable}">No Touching!</li>
Sources:
ngClass: https://docs.angularjs.org/api/ng/directive/ngClass
More info on pointer-events here: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
Reasonably supported in everything but IE: http://caniuse.com/#feat=pointer-events
You can use this driective:
(function () {
'use strict';
angular
.module('app.widgets')
.directive('zzDisableClickIf', disableClickIf);
function disableClickIf($parse, $rootScope) {
// Usage:
// <li>
// <a ui-sref="somestate" zz-disable-click-if="!model.isValid()">Go Somestate</a>
// </li>
return {
// this ensure zzDisableClickIf be compiled before ngClick
priority: 100,
restrict: 'A',
compile: function ($element, attr) {
var fn = $parse(attr.zzDisableClickIf);
return {
pre: function link(scope, element) {
var eventName = 'click';
element.on(eventName, function (event) {
var callback = function () {
if (fn(scope, { $event: event })) {
// prevents ng-click to be executed
event.stopImmediatePropagation();
// prevents href
event.preventDefault();
return false;
}
};
if ($rootScope.$$phase) {
scope.$evalAsync(callback);
} else {
scope.$apply(callback);
}
});
},
post: function () { }
}
}
}
}
} ());
This directives stops the action of if zz-disable-click-if='false'
var app=angular.module("app",[])
app.controller("itemController",function($scope){
$scope.condition=false;
$scope.disableLink=function(){
$scope.condition=!$scope.condition;
}
});
<html>
<style>
.not-active {
pointer-events: none;
cursor: default;
color: #ddd;
}
</style>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="app">
<div ng-controller="itemController">
<div >
<ul class="list-group" >
<li class="list-group-item"><a href='https://www.google.co.uk/webhp?hl=en'>Item1</a></li>
<li class="list-group-item"><a ng-class={'not-active':condition} href='https://www.google.co.uk/webhp?hl=en'>Item2</a></li>
<li class="list-group-item"><a href='https://www.google.co.uk/webhp?hl=en'>Item3</a></li>
</ul>
</div>
<input type='button' value='Enable/Disable Link' ng-click='disableLink()'>
</div>
</body>
</html>
What about just using ng-show / ng-hide to show an <a>or a <span> depending on the boolean holding the fact that the item should be clickable or not ?
That's not the sexiest, but it's still clean.
Here is a plunker (i assumed your list is dynamically created but that's not something really important)
The HTML :
<ul class="list-group" >
<li ng-repeat="item in items" class="list-group-item">
<span ng-hide="item.clickable">{{item.name}}</span>
<a ng-show="item.clickable" href=''>{{item.name}}</a>
<button ng-click="item.clickable = !item.clickable">Disable/Enable</button>
</li>
</ul>
I also added for the demo a button to disable/enable the link.
Tell me if what do you think about this solution.

How to display custom layout with ng-repeat

Edit: My original question was not good enough, so edited it now.
Hi Im new to angular and im trying to display a custom Layout
for my data list with ng-repeat. I cant use ng-class, as I would like to display diffent model vaules too.
I implemented a function in my controller, that calculates true or false according to my desired design. Then im trying to use ng-if to display my desired HTML with the data. The way I implemeted seems a bit awkward, especially if the layout gets more complicated, is there a better way to achieve this behaviour?
Here a sample: http://plnkr.co/edit/puE7OE?p=info
Controller:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.eventModels=[{name:'event1', description: 'description1'}, {name:'event2', description: 'description2'},
{name:'event3', description: 'description3'}, {name:'event4', description: 'description4'},
{name:'event5', description: 'description5'}, {name:'even6', description: 'description6'}, {name:'even7', description: 'description7'}];
var counter = 0;
this.isLarge = false;
$scope.isLargeContainer = function() {
if(counter === 0) {
this.isLarge = true;
counter++;
} else {
this.isLarge = false;
if(counter === 2) {
counter = 0;
} else {
counter++;
}
}
};
});
View:
<body ng-controller="MainCtrl">
<section ng-repeat="(key, eventModel) in eventModels" >
<div ng-init="isLargeContainer(eventModel)"></div> <!--the only way I found to call a function within the repeat directive.-->
<div ng-if="isLarge">
<!--Display large content -->
<p class='large'>my large event: {{eventModel.name}}, {{eventModel.description}}</p>
</div>
<div ng-if="!isLarge">
<!--Display content small-->
<p class='small'>{{eventModel.name}}</p>
</div>
</section>
</body>
Thanks a lot in advance!
Im using Anguler 1.3.3
I just solved your problem. You can find the solution here:
http://jsfiddle.net/anasfirdousi/46saqLmw/
Here is the HTML
var myApp = angular.module('myApp',[]);
function myController($scope){
$scope.msg = 'Learning Angular JS ng-class Directive';
$scope.menu = [ 'Menu Item 1','Menu Item 2','Menu Item 3','Menu Item 4'];
}
.large {
font-size:16px;
}
body{
font-size:12px;
}
<div ng-app="myApp" ng-controller="myController">
{{ msg }}
<ul>
<li ng-repeat="(key, value) in menu" ng-class="{'large': $index==2 }"> {{ value }} </li>
</ul>
</div>
In your case, you actually have to use ng-class with expressions. The class is applied only if the condition holds true.
http://jsfiddle.net/anasfirdousi/cuo6cn3L/
Check the above link. This is another example if you want to do it on any specific condition. You can call a function which checks a condition and returns either a true or a false rather than using an inline expression.
var myApp = angular.module('myApp',[]);
function myController($scope){
$scope.msg = 'Learning Angular JS ng-class Directive';
$scope.menu = [ 'Menu Item 1','Menu Item 2','Menu Item 3','Menu Item 4'];
$scope.CheckSometing = function(v){
if(v=='Menu Item 3'){
return true;
}
else
{
return false;
}
}
}
.large {
font-size:16px;
}
body{
font-size:12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
{{ msg }}
<ul>
<li ng-repeat="(key, value) in menu" ng-class="{'large': CheckSometing(value) }"> {{ value }} </li>
</ul>
</div>

Resources