I have menu with sections and subsections, like this:
Section 1
Sub 1.1
Sub 1.2
Section 2
Sub 2.1
Sub 2.2
I want to hide subsections and show one of them by clicking on section (click on Section 2):
Section 1
Section 2
Sub 2.1
Sub 2.2
Here is my code and JSFiddle:
<div ng-controller="MyCtrl">
<div ng-repeat="(meta, counts) in info">
{{ meta }}
<ul class="subsection">
<li ng-repeat="(group, cnt) in counts">
{{ group }}
</li>
</ul>
</div>
</div>
Controller:
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.name = 'Superhero';
$scope.info = { "one": { "a": 1, "b": 2 },
"two" : { "c": 3, "d": 4 }};
$scope.display = function(meta) {
// ????
};
}
CSS:
ul.subsection {
display: none;
}
How can I fix this code to show one of the subsection by click on the section ?
Update: I fixed the link on JSFiddle
Since ng-repeat creates its own scope, you can simply toggle a variable within the loop, and use ng-show on that variable:
<div ng-repeat="(meta, counts) in info">
{{ meta }}
<ul class="subsection" ng-show="display">
<li ng-repeat="(group, cnt) in counts">
{{ group }}
</li>
</ul>
</div>
Edit: If you can only show one function at a time, then you can do what you were trying to do in your original code with a function:
<div ng-repeat="(meta, counts) in info">
{{ meta }}
<ul class="subsection" ng-show="sectionIndex == $index>
<li ng-repeat="(group, cnt) in counts">
{{ group }}
</li>
</ul>
</div>
$scope.display = function(index) {
$scope.sectionIndex = index;
}
You can simply do something like this:
<div ng-repeat="(meta, counts) in info">
{{meta}}
<ul class="subsection" ng-show="$parent.display == meta">
<li ng-repeat="(group, cnt) in counts">
{{ group }}
</li>
</ul>
</div>
Note, that you can refer $parent scope to avoid local scope display property.
In this case you don't need CSS rule. Bonus point is that you can set in controller $scope.display = 'two' and the second item will expand.
However cleaner way would be using a controller function as demonstrated by #tymeJV, this is the best approach.
Demo: http://plnkr.co/edit/zXeWjXLGHMv0BZZRZtud?p=preview
Related
How to show comments in items?
This is where items save
$scope.items = [
{ 'item': 'one',
'comments':[{'comment':'comment'}]
},
{ 'item': 'two',},
{'item': 'three'}
];
<ul>
<li ng-repeat="ite in items">
{{ite.item}} {{ite.comments.length}}
<button ng click="remove($index)">Remove</button> <div ng-repeat="c in ite.comments">{{c.comment}}</div>
</li>
</ul>
http://plnkr.co/edit/19w1Q3XhoWQcpxm5SuxX?p=preview
You Just missed to add your comment Div in between the list tag. please update the code like above code. I have checked on Plunker.
<li ng-repeat="ite in items">
{{ite.item}} {{ite.comments.length}}
<button ng-click="remove($index)">Remove</button> <div ng-repeat="c in ite.comments">{{c.comment}}</div></li>
I have a list that is generated via ng-repeat. E.g i have the html like this
<ul class="my-list">
<li>List Item</li>
<li>List Item</li>
<li>List Item</li>
<li>List Item</li>
<li>List Item</li>
<li>List Item</li>
<li>List Item</li>
<li>List Item</li>
</ul>
I want to add a class of .last-itmes to the last 3 list items using angular. How can i do this?
In ng-repeat, Angular provides $index, $first, $last to get the index position of list item.
In your case you can use $last and substract from it like $last-1, $last-2.
Sample code :
<li ng-repeat="item in itemList"
ng-class="{'last':($index === $last) || ($index === ($last-1)) || ($index === ($last-2))}"
>List Item
</li>
Please see demo below
ie:
ng-class="{'last-itmes':$index>=data.length-3}"
var app = angular.module('app', []);
app.controller('homeCtrl', function($scope) {
$scope.data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
});
.last-itmes {
color: red
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="homeCtrl">
<ul class="my-list">
<li ng-repeat="i in data" ng-class="{'last-itmes':$index>=data.length-3}">{{i}}</li>
</ul>
</div>
</div>
My suggestion is that you can go for Directives which is a neat and clean way
var app = angular.module('myApp', []);
app.controller('ArrayController', function ($scope) {
$scope.datas = ['List Item',
'List Item',
'List Item',
'List Item',
'List Item',
'List Item',
'List Item',
'List Item'];
})
.directive("itemWatch", [function () {
return {
scope: {
index: '=index',
length: '=length'
},
replace: false,
link: function ($scope, $element, $attrs, Controller) {
if ($scope.length - $scope.index <= 3) {
$element.addClass('last-itmes');
}
}
};
}]);
.last-itmes
{
color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='myApp' ng-controller="ArrayController">
<ul class="my-list">
<li ng-repeat="item in datas track by $index" index="$index" length="datas.length" item-watch>{{item}}</li>
</ul>
</div>
You can use with js object and ng-show.
var items = [
{id:1,isLast:false}
{id:2,isLast:true}
{id:3,isLast:true}
]
And your html with angularjs:
<li ng-repeat="item in items">
<div class="last-items" ng-show="item.isLast">
</li>
When setting up your ng-repeat, you can use track by $index to determine which position you are on. Doing that, you can easily do things within the repeat. To get it to add a class for just the last three items, you can put a condition on the ng-class directive like so:
<table>
<tbody ng-repeat="row in people track by $index">
<tr ng-class="{'blue': $index > people.length - 4 }">
<td>
<p style="font-weight:bold;">{{ row }}</p>
</td>
</tr>
<tbody>
</table>
I've made a plunker to show an example:
http://plnkr.co/edit/g24eYggfIRFS2El8R5Mu
I want to output a list of <li> elements using ng-repeat="obj in links", where links is an array of objects with href and text properties:
$scope.links = [
{ href: '/asdf', text: 'asdf'},
{ href: '/qwer', text: 'qwer'},
/* etc. */
{ href: '/zxcv', text: 'zxcv'}
];
But I want the ng-repeat loop to change what it does when it reaches a certain object in that array. Specifically, I want the loop to create hyperlinks for every object until obj.href==location.path() -- and after that, I just want to write out the text inside a <span>.
Currently, I'm solving this by creating both links and spans each time in the loop:
<ul>
<li ng-repeat="obj in links" ng-class="{active: location.path()==obj.href}">
<a ng-href="{{obj.href}}">{{obj.text}}</a>
<span>{{obj.text}}</span>
</li>
</ul>
plunkr
I then use CSS to hide all hyperlinks after the active class and hide all spans before it. But I don't want to just hide the links after the condition matches -- I want them to be completely removed from the DOM.
So there are two things you must do.
Find the index of the active element
Only show links up to the active index, and after that only show spans
What about this:
In your controller
$scope.lastIndex = 0;
$scope.$watch('links', function(newVal, oldVal){
for(var i=0; i< newVal.length; i++){
if (newVal[i].href == location.path()){
$scope.lastIndex = i
break;
}
}
}
In your HTML :
<ul>
<li ng-repeat="obj in links">
<a ng-if="$index <= {{lastIndex}}" ng-href="{{obj.href}}">{{obj.text}}</a>
<span ng-if="$index > {{lastIndex}}">{{obj.text}}</span>
</li>
</ul>
please see that example http://jsbin.com/cifef/1/edit
for your solution you need to replace $scope.location.href by location.path()
$scope.isLast = false;
$scope.getValue = function(obj)
{
if( obj.href==$location.path() || $scope.isLast )
{
$scope.isLast = true;
obj.isLast = true;
}
};
HTML:
<ul>
<li ng-repeat="obj in links" ng-class="{active: location.href==obj.href}" ng-init="getValue(obj)">
<a ng-href="{{obj.href}}" ng-hide="obj.isLast">{{obj.text}}</a>
<span ng-show="obj.isLast">{{obj.text}}</span>
</li>
</ul>
I'm using the ng-repeat to list all the products, and I want to print out a star symbol x times depending on the product.rating. So, the code looks like following:
<p class="bs-rating"><i class="fa fa-star" ng-repeat="i in getRating({{ product.rating }}) track by $index"></i></p>
However, it parsed the product.rating as a String: Error: [$parse:syntax] http://errors.angularjs.org/1.3.0-beta.8/$parse/syntax?p0=product.rating&p1=is
I have tried to remove the curly brackets, {{ }}:
<p class="bs-rating"><i class="fa fa-star" ng-repeat="i in getRating(product.rating) track by $index"></i></p>
It gave me undefined. My getRating() is declared as following:
$scope.getRating = function(rating){
return new Array(parseInt(rating));
}
Could you help me figure it out how to pass a variable to ng tag?
The problem is on getRating function ie on generating the array.
I have developed an alternative solution on this link rating using ng-repeat #jsfiddle
<div ng-app="myApp" ng-controller="myCtrl">
<ol>
<li ng-repeat="product in products">
{{product.name}}
(
<span style="font-weight:bold" ng-repeat="i in
getRating(product.rating)">
x
</span>
)
</li>
</ol>
var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope){
$scope.products = [
{name : "product1", rating:3},
{name : "product2", rating:5},
{name : "product3", rating:1}
];
$scope.getRating = function(rating){
var ratingArray = [];
for (var i = 1; i <= rating; i++) {
ratingArray.push(i);
}
return ratingArray;
};
});
Hopefully it will help.
Cheers
I'd like to access to the parameters of the next item on screen when clicking on a button.
I use a ng-repeat in my html file:
<li ng-repeat="item in items | filter:query" ng-show="isSelected($index)">
<img src="xxx.jpg" />
</li>
And the index in my Controller with a loop:
$scope.itemNext = function () {
$scope._Index = ($scope._Index < $scope.nbItems - 1) ? ++$scope._Index : 0;
$scope.functionToCallWithNextItem(nextItem.param1);
};
A simple $scope.items[$scope._Index].param1 instead of nextItem.param1 wouldn't work as the data is filtered so $index+1 from $scope.items isn't necessarily the good one.
Any idea ?
You can assign your filtered data to a variable:
<li ng-repeat="item in (filteredItems = (items | filter:query))">
Then use $index + 1 to get the next item:
<a ng-click="itemNext(filteredItems[$index + 1])">
Demo: http://plnkr.co/edit/OdL5rIxtTEHnQCC3g4LS?p=preview
It's simpy that
<div ng-repeat="item in items">
current: {{item.value}}
next: {{ items[$index + 1].value}}
previous: {{ items[$index - 1].value}}
</div>