angularjs pass index through directive - angularjs

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¿?

Related

Using the same ng-click in different classes

So the thing is:
I have four cards and I have a ng-click on the first one with a function named OpenCard().
When I click, it shows its hidden content.
I wanna do the same for the rest of the cards, using the same call to OpenCard().
My four classes have the same name "rowCont" and the hidden content inside that "rowCont" is different:
<div class="rowCont" ng-click="OpenCard()" ng-class="{'active': isActive}">
<div class="hiddenContent">
<div class="animate-show" ng-show="cardVisible">
</div>
</div>
</div>
$scope.isActive = false;
$scope.OpenCard = function () {
if($scope.isActive == false) {
$scope.isActive = true;
$scope.cardVisible = true;
} else {
$scope.isActive = false;
$scope.cardVisible = false;
}
}
I'm using Angular 1.6.0
Do you have an idea how can I refer to one card in specific using the same function on ng-click? Cause when I click one in one closed card it shows the content of all cards.
<div class="row">
ng-repeat="x in current_tab
ng-class="{active1 : activeMenu === x}"
ng-click="setActive(x);"> {{x.userId}}
</div>
$scope.menuItems = $rootScope.current_tab;
$scope.activeMenu = $scope.menuItems[0];
$scope.setActive = function(menuItem) {
$scope.activeMenu = menuItem
}
var app = angular.module("ngClickApp", []);
app.controller('ngClickCtrl', ['$scope', function ($scope) {
$scope.cards = [{
isActive: false,
title: '1',
content: 'content 1'
}, {
isActive: false,
title: '2',
content: 'content 2'
}];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-app="ngClickApp">
<head>
<title>Validation messages</title>
</head>
<body ng-controller="ngClickCtrl">
<div class="rowCont" ng-repeat="card in cards track by $index" ng-click="card.isActive=!card.isActive" ng-class="{'active': c.isActive}">
card {{$index}}
<div class="hiddenContent">
<div class="animate-show" ng-show="card.isActive">
{{card.content}}
</div>
</div>
</div>
</body>
</html>
You can store card's visibility in an array ($scope.cardsVisible = [];), and pass an index in each call to OpenCard(cardIndex).
Then, display it conditionnaly in your view:
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.cardsVisible = [];
$scope.OpenCard = function(cardIndex) {
$scope.cardsVisible[cardIndex] = true;
$scope.isActive = cardIndex;
}
}
.active {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<div ng-click="OpenCard(1)" ng-class="{'active': isActive == 1}">
Card 1
<div ng-show="cardsVisible[1]">
This card is visible
</div>
</div>
<div ng-click="OpenCard(2)" ng-class="{'active': isActive == 2}">
Card 2
<div ng-show="cardsVisible[2]">
This card is visible
</div>
</div>
</div>

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>

Ng repeat and ng class mistake

I have some categories and subcategories.When I select category it apears subcategories.Next I want to select a subcategory of category selected but the class is changing.
I want, when I select a category to be able to select a subcategory of that category.Here is the codepen :
http://codepen.io/anon/pen/GZKBaW.
Thanks for help! :)
<html lang="en" ng-app="StarterApp">
<head>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/angular_material/0.8.3/angular-material.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js">
</script>
</head>
<body ng-controller="AppCtrl">
<ul class="main">
<li ng-repeat="a in categories"
ng-class="{active : toggled==$index,none:toggled!=$index}"
ng-click="set($index)">{{a.name}}
<ul>
<div ng-show="showData">
<li ng-class="{'active':event==$index,'none':event!=$index}" ng-repeat="b in subcategories" ng-click="setSubcategory($index,b)">{{b}}</li>
</ul>
</li>
</ul>
</body>
</html>
Shouldn't access html directly,
Your'e accessing html directly and you shouldn't in your case. i would change your controller to
var app = angular.module('StarterApp', []);
app.controller('AppCtrl', ['$scope', function($scope) {
$scope.categories = [{
'name': 'work',
'subcategories': ['saved', 'study', 'plm']
}, {
'name': 'move',
'subcategories': ['saved', 'study', 'xxx']
}, {
'name': 'flirt',
'subcategories': ['saved', 'travel', 'aaa']
}];
$scope.setSelectedCategory = function(category){
$scope.selectedCategory = category;
}
$scope.setSelectedSubcategory = function(subcategory){
$scope.selectedSubcategory = subcategory;
}
}]);
and your html to,
<ul class="main">
<li ng-repeat="category in categories" ng-click="setSelectedCategory(category)" ng-class="{'active' : category == selectedCategory}">
{{category.name}}
<ul ng-show="category == selectedCategory">
<li ng-class="{'active':selectedSubcategory == subcategory}" ng-repeat="subcategory in category.subcategories" ng-click="setSelectedSubcategory(subcategory)">{{subcategory}}</li>
</ul>
</li>
</ul>
http://codepen.io/anon/pen/XdrPqm

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>

Access child scope corresponding to a model variable

I have a list of items and I've rendered them in a template via ng-repeat. Each of them is controlled by an itemController which exposes some behavior for item (e.g. grabing focus). Here is the HTML:
<body ng-controller="mainController">
<button ng-click="addItem()">add</button>
<ul>
<li ng-repeat="item in items" ng-controller="itemController">
<div ng-if="item.isEditing">
<input ng-model="item.name"/>
<button ng-click="item.isEditing=false">done</button>
</div>
<span ng-if="!item.isEditing">{{item.name}}</span>
</li>
</ul>
</body>
In the mainController, I have a function for adding a new item to items. Here is the code for mainController:
app.controller('mainController', function($scope){
$scope.items = [
{
name: "alireza"
},
{
name: "ali"
}
];
$scope.addItem = function(){
$scope.items.push({isEditing: true});
}
});
Whenever I add an item to items array, a corresponding li element is added into the view which is controlled by an instance of itemController, and the corresponding model is the new item I've just added (or maybe the scope of the itemController, which contains item).
Problem:
When I add some item to items, I only have access to item and not the scope of the recently created item. So I can't run some function (like grabFocus) on the scope of new item.
Is it something semantically wrong in my design? What is the canonical approach for this problem?
Plunker link
Here is the plunker link with related comments
You can use $broadcast from the parent scope, along with $on from the child scope, to notify the child scopes of the newly added item. And by passing (as an argument) the $id of the child scope that corresponds to the newly added item, each child catching the event can know whether or not it's the one that needs to have grabFocus() called.
Here's a fork of your Plunker that uses that approach. I wasn't sure what you were trying to accomplish with $element.find(":text").focus(); in your original Plunker, so I tweaked it to toggle a $scope property that in turn controlled a style in the view. The newly added item will be red (by calling its own grabFocus function to toggle the flag to true), and the others will be black (by calling their own loseFocus function to toggle the flag to false).
Modified HTML (just the repeated li):
<li ng-repeat="item in items" ng-controller="itemController">
<div ng-if="item.isEditing">
<input ng-model="item.name"/>
<button ng-click="item.isEditing=false;handleItemAdded($index);">done</button>
</div>
<span ng-if="!item.isEditing" ng-style="{ color: isFocused ? 'red' : 'black' }">{{item.name}}</span>
</li>
Full JavaScript:
var app = angular.module("app",[]);
app.controller('mainController', function($rootScope, $scope){
$scope.items = [ { name: "alireza" }, { name: "ali" } ];
$scope.addItem = function(){
$scope.items.push({isEditing: true});
};
$scope.handleItemAdded = function (index) {
// $rootScope.$broadcast('item-added', { index: index });
for(var cs = $scope.$$childHead; cs; cs = cs.$$nextSibling) {
if (cs.$index === index) {
$rootScope.$broadcast('item-added', { id: cs.$id });
break;
}
}
};
});
app.controller('itemController', function($scope, $element){
$scope.$on('item-added', function (event, args) {
if ($scope.$id === args.id + 1) {
$scope.grabFocus();
} else {
$scope.loseFocus();
}
});
$scope.grabFocus = function() {
$scope.isFocused = true;
};
$scope.loseFocus = function() {
$scope.isFocused = false;
};
});
I changed your approach a little bit by creating an unique id for every input, based on its index number. See code below, hope it helps.
// Code goes here
var app = angular.module("app",[]);
app.controller('mainController', function($scope,$timeout){
$scope.items = [
{
name: "alireza"
},
{
name: "ali"
}
];
$scope.addItem = function(){
$scope.items.push({isEditing: true});
$timeout(function(){
document.getElementById("newItem"+($scope.items.length-1)).focus();
},0)
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.3.0" data-semver="1.3.0" src="//code.angularjs.org/1.3.0/angular.js"></script>
<link href="style.css" rel="stylesheet" />
<script src="script.js"></script>
</head>
<body ng-controller="mainController">
<button ng-click="addItem()">add</button>
<ul>
<li ng-repeat="item in items">
<div ng-if="item.isEditing">
<input ng-model="item.name" id="newItem{{$index}}"/>
<button ng-click="item.isEditing=false">done</button>
</div>
<span ng-if="!item.isEditing">{{item.name}}</span>
</li>
</ul>
</body>
</html>

Resources