How to add class to current item in Angular JS? - angularjs

I have HTML code is formatted via ng-repeat:
<div id="list">
<div class="item" ng-click="Select()"></div>
<div class="item" ng-click="Select()"></div>
<div class="item" ng-click="Select()"></div>
</div>
How I can add class to current .item where was called method Select() after response AJAX?
Angular JS:
$scope.function = Select() {
Ajax () {
response (){
// Here add CSS class to clicked element .item
}
}
}

You will need to do: $scope.select= function() {. Your ng-click is fine.

Manipulating DOM from controller is bad practice & you shouldn't do that wherever you had directive like ng-class
Basically you need to use ng-class directive & selected property in each item to have a track of selected items.
Markup
<div class="item" ng-class="{selected: item.selected}" ng-repeat="item in items"></div>
Controller
$scope.Select = function(item) {
$http.get('url').success(function(){
item.selected = true;
})
}

Related

How to forbideen updating model in Angular JS?

I have nested controller like:
<div ng-controller="MainController">
<div ng-controller="ChildController"></div>
</div>
Inside Child controller there is function:
$scope.isStatus = function() {
return function(item) {
}};
This function is used in ng-repeat.
So, problem is when I modify model of controller MainController it reload model of ChildController, It means that function isStatus() works again and reload model. How to fix it?
You can use controllerAs syntax to avoid this
<div ng-controller="MainController as main">
<div ng-controller="ChildController as child">
<ul ng-repeat ="item in child.item">
</div>
</div>
And in js
function ChildController (){
var vm = this;
vm.isStatus = function() {
return function(item) {
}};
}
you can see more infomation in here
https://github.com/johnpapa/angular-styleguide/tree/master/a1#controllers

Angularjs : ui-sref state change in url not showing submenu

In angularjs to show/hide dynamic submenu, I am adding and removing dynamic classes in js file. Every time when the state changes in url (i.e ui-sref={{mymenu.url}}) sub menu is not visible. If there is no state change sub menu is working properly. Can anyone please suggest.
Html
<li ng-repeat='mymenu in menuItems' ng-click="showHideMenu($event);" >
<a class="iconsize" ui-sref={{mymenu.url}}>
<i class={{mymenu.image}}></i> <strong>{{mymenu.menuName}}</strong>
<span class="fa fa-chevron-down"></span>
</a>
<ul class="submenuHide">
<li class="" ng-repeat='submenu in mymenu.submenu'>
<a>{{submenu.submenuName}}</a>
</li>
</ul>
JS
$scope.showHideMenu = function(event) {
var classname = event.target.parentElement.parentElement.children[1].className;
if(classname == 'submenuHide'){
$(event.target.parentElement.parentElement.children[1]).removeClass('submenuHide');
$(event.target.parentElement.parentElement.children[1]).addClass('submenuShow');
}else if(classname == 'submenuShow'){
$(event.target.parentElement.parentElement.children[1]).removeClass('submenuShow');
$(event.target.parentElement.parentElement.children[1]).addClass('submenuHide');
}
}
A couple things. One, you'll need to make sure your menu is outside of the individual templates you're working with. Two, using ng-class bound to an ng-model ensures that your menu state is included in the digest cycle. This will save you the jqLite and dom parsing logic.
Here's an example plunker.
So your code might look like this:
<body ng-controller="MainCtrl">
<a ui-sref="hello">Hello</a>
<a ui-sref="about">About</a>
<button ng-click="toggleMenu()">Show / Hide Menu</button>
<ui-view></ui-view>
<ul ng-class="{showMenu: show, hideMenu: !show}">
<li ng-repeat="letter in ['a','b','c','d']">{{letter}}</li>
</ul>
</body>
With this JS:
app.controller('MainCtrl', function($scope) {
$scope.show = false;
$scope.toggleMenu = function() {
$scope.show = !$scope.show;
};
});

how to bind $index from ng-repeat to controller

In Angular I wanted to bind $index to controller. How can I send $index value in to my controller. Here is my html code.
<body>
<div class="container">
<div class="row row-content" ng-controller="demoController as demoCtrl">
<ul>
<li ng-repeat="val in demoCtrl.list" >Hello {{$index}}</li>
</ul>
</div>
</div>
Here is my controller code
var app = angular.module('confusionApp',[])
app.controller('demoController', function(){
var list = [1,2,3,4,5];
this.list = list;
var array = ['abc','def','ghi','jkl','mno']
this.array = array
console.log(this.array[index]);
});
I need to use ng-modal in HTML and bind that value to some variable in my controller.
Based on the selection of index, it should check in array and respective array should have to print.
Can any of you please help
To get your current iteration position in your controller you have define a function.
So your html code like this.
<body>
<div class="container">
<div class="row row-content" ng-controller="demoController as demoCtrl">
<ul>
<li ng-repeat="val in demoCtrl.list" ng-click="dispArray($index)">Hello {{$index}}</li>
</ul>
</div>
</div>
And your controller code
var app = angular.module('confusionApp',[])
app.controller('demoController', function($scope){
$scope.dispArray = function(index){
// console.log(index);
// your code
}
});
Depending on what you're trying to accomplish you might be better served creating a custom iterator.
function makeIterator(array){
var nextIndex = 0;
return {
next: function(){
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
}
}
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators
Angular is going to iterate over everything in the list when you use ngRepeat. If you're trying to track which list item a user clicks then you'll just add that in there using $index.
<li ng-repeat="val in demoCtrl.list" >
<span ng-click="demoCtrl.userClicked($index)"> Hello {{$index}}</span>
</li>
If you're just trying to print the data in each item, ng-repeat is already iterating everything for you.
<li ng-repeat="val in demoCtrl.list" >
<span ng-click="demoCtrl.userClicked($index)"> Hello {{val}}</span>
</li>
It all depends on what you're trying to do.
i dont konw what u want to do. if u want to use event. you can pass $index to your controller function like:
<li ng-repeat="val in demoCtrl.list" ng-click="getIndex($index)">Hello {{$index}}
$scope.getIndex = function($index) {
console.log($index)
}
hope to help u.

applying class using ng-class for nested items in Angularjs

I am displaying the menu items in the below format. The data contains list of items and for each item there is a subitem. I need to apply the selected class for the subitem selected and all other subitems for all the items should be deselected. How to do this inside the controller. I tried by adding the ng-click event inside the html and toggling the class inside the controller but it is not applying for all the other subitems inside other items. Both html and controller code is shown below for more details.
<ol ng-model="data">
<li ng-repeat="item in data" collapsed="true">
<div ng-click="toggle(this)">
<a class="btn btn-success btn-xs" ng-if="item.children && item.children.length > 0">{{item.name}}</a>
</div>
<ol ng-model="item.children" ng-class="{hidden: collapsed}">
<li ng-repeat="subItem in item.children" ng-model="subItem.name" collapsed="true" ng-click="handleClick(subItem)">
<div ng-class="{'selected-li': subItem.value, 'deselected-li': false}">
{{subItem.name}}
</div>
</li>
</ol>
</li>
</ol>
Inside my controller I am having the code as below:
$scope.toggle = function (scope) {
scope.toggle();
};
$scope.handleClick=function(subitem){
subitem.value = subitem.value ? !subitem.value: true;
}
The data object used inside the UI contains the children also. Please let me know where I am going wrong.
HTML
<li ng-repeat="subItem in item.children" ng-model="subItem.name" collapsed="true" ng-click="handleClick($index, item.children)">
<div ng-class="{'selected-li': subItem.value, 'deselected-li': false}">
{{subItem.name}}
</div>
</li>
JS
$scope.handleClick = function(index, subItems) {
for(var i = 0; i < subItems.length; i++) {
if(i == index) {
subItems[i].value = true;
} else {
subItems[i].value = false;
}
}
}
What I'm doing here is, the index of the sub item and the entire item.children array are sent to the ng-click handler method and then in a for loop I am updating the value of all the sub items in that list.

Programmatically create an ng-show value in ng-repeat

I have the following:
<div class="row" ng-repeat="item in items " ng-cloak>
<div ng-show="unique{{$index}}" class="ng-hide">
<button ng-click="remove('{{$index}})">Remove</button>
</div>
I want to create a unique value for every div item repeated,like so:
<div ng-show="unique1" class="ng-hide">
<button ng-click="remove('unique1')">Remove</button>
<div ng-show="unique2" class="ng-hide">
<button ng-click="remove('unique2')">Remove</button>
so that in my controller I can have an action, in this case remove(), that will toggle that attribute.
scope.remove = function(uniqueAttribute) {
$scope[uniqueAttribute] = false;
}
I was able to generate the html using $index but that code does not work and I am sure not sure how to go about accomplishing this.
You can add a new field called show to each object and then you can eliminate all logic relating to the $index.
<div ng-app ng-controller="Ctrl">
<div class="row" ng-repeat="item in items" ng-cloak>
<div ng-show="item.show">
<button ng-click="remove(item)">Remove</button>
</div>
</div>
</div>
function Ctrl($scope) {
$scope.items = [{
item1: 1,
show: true
}, {
item1: 2,
show: true
}, {
item1: 3,
show: false
}];
$scope.remove = function (item) {
item.show = false;
}
}
DEMO
Most attributes in Angular are either evaluated or interpolated. Evaluation is like a restricted form of eval(), interpolation is when the double curly braces get filled in. It looks like you're expecting the ng-show to be interpolated then evaluated, but none of the built-in directives do this. They do one or the other but not both. For ng-show specifically it just does evaluation, so your curly braces pass through literally. This would be an invalid expression.
My suggestion is this: Since ng-repeat creates a new scope for each repeated item, you can just do this:
<div class="row" ng-repeat="item in items" ng-cloak>
<div ng-show="!hide" class="ng-hide">
<button ng-click="hide = true">Remove</button>
</div>
Of course, why keep a bunch of hidden items around. Why not have ng-click="remove(item)" and a remove function that removes from items? Then the ng-repeat updates naturally.
$scope.remove = function(item) {
var index = this.items.indexOf(item);
if (index != -1) {
this.items.splice(index);
}
};
Or something like that.
You don't need to use {{ }} in angular's attributes. It will automatically evaluate your scopes.
<div class="row" ng-repeat="item in items" ng-cloak>
<div ng-show="'unique' + $index" class="ng-hide">
<button ng-click="remove('unique' + $index)">Remove</button>
</div>

Resources