Updating Repeat Items Index - angularjs

I have a collection of items which I am displaying in my view using ng-repeat. I also have two buttons, one to move the item to the left, and the other to move the item to the right.
View
<div data-ng-repeat="item in items">
<!--Move Item Index to the Left-->
<a href="#">
<i ng-click="move($index, $index - 1)" class="fa fa-chevron-left"></i>
</a>
<!--Move Item Index to the Right-->
<a href="#" >
<i ng-click="move($index, $index + 1)" class="fa fa-chevron-right"></i>
</a>
<h1>{{item.name}}</h1>
</div>
Controller
$scope.move = function(fromIndex, toIndex) {
var element = $scope.items[fromIndex];
$scope.items.splice(fromIndex, 1);
$scope.items.splice(toIndex, 0, element);
};
The array is updating but the changes are not reflected in the UI.
How can I get the changes to reflect in the UI?

It is working correctly. Just add some text in the i tag and click on it.
<div data-ng-repeat="item in items">
<!--Move Item Index to the Left-->
<a href="#">
<i ng-click="move($index, $index - 1)" class="fa fa-chevron-left">Left</i>
</a>
<!--Move Item Index to the Right-->
<a href="#" >
<i ng-click="move($index, $index + 1)" class="fa fa-chevron-right">Right</i>
</a>
<h1>{{item}}</h1>
</div>

It is just working, see JSFiddle
(I removed the css classes because no css lib available in the example)
index.html
<div id="app" ng-controller="MainCtrl">
<div data-ng-repeat="item in items">
{{item}}
<!--Move Item Index to the Left-->
<
<!--Move Item Index to the Right-->
>
</div>
</div>
app.js
angular.module('myApp', [])
.controller('MainCtrl', function ($scope) {
$scope.items = ['a', 'b', 'c'];
$scope.move = function (fromIndex, toIndex) {
var element = $scope.items[fromIndex];
$scope.items.splice(fromIndex, 1);
$scope.items.splice(toIndex, 0, element);
};
});
angular.bootstrap(document.querySelector('#app'), ['myApp']);
Note that you cannot move the first item back and the last item forward, because the first item already is the first of the list :).
Don't forget to add some text (for screenreaders!) to the chevrons and it's better to set the ng-click on the anchors.
href="#" is not necessary. You don't want to link to # (which usually is the landing page of your app) -> <a href ng-click="...">
Even better: if you want the have a pointer cursor, you could use CSS for this: cursor: pointer and omit the href.

Well, I created this example on Plnkr and it is changing position
I just moved MOVE method to <a> tag.
<!doctype html>
<html ng-app>
<head>
<script src=".../angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="Ctrl">
<div data-ng-repeat="item in items">
<!--Move Item Index to the Left-->
<a href="#" ng-click="move($index, $index - 1)">
<i class="fa fa-chevron-left"></i>
Left
</a>
<!--Move Item Index to the Right-->
<a href="#" ng-click="move($index, $index + 1)" >
<i class="fa fa-chevron-right"></i>
Right
</a>
<h1>{{item.name}}</h1>
</div>
</div>
</body>
</html>
function Ctrl($scope) {
$scope.items = [{name:'aa'}, {name:'bb'}, {name:'cc'},{name:'dd'}]
console.log($scope.items)
$scope.move = function(fromIndex, toIndex) {
console.log($scope.items)
var element = $scope.items[fromIndex];
$scope.items.splice(fromIndex, 1);
$scope.items.splice(toIndex, 0, element);
};
}

Related

Model updates in directive do not update view

angular.module('myApp')
.component('sideNav', {
controller: function SideNavController($scope) {
$scope.navigation = {};
$scope.click = function(key) {
$scope.navigation[key] = !$scope.navigation[key];
}
},
templateUrl: 'components/side-nav/side-nav.html',
})
to be used as simply
<side-nav></side-nav>
The template is
<!-- other li items -->
<li ng-init="navigation.charts = false"
ng-click="click('charts')">
<a href="#">
<i class="fa fa-bar-chart-o fa-fw"></i>
Charts {{ navigation.charts }}
<span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level"
ng-show="navigation.charts">
<li>
Charts
</li>
<li>
Graphs
</li>
</ul>
</li>
navigation.charts is correctly initialized to false and hence the li > ul is hidden. Clicking the top level li item updates the navigation object but the view does not update. I was expecting the li > ul element to get displayed.
Plunkr: https://plnkr.co/edit/UJpdFErwVUzsCd65hlW0?p=preview
Clicking on the link reloads the page and re-initializes the directive. Try modifying to:
<li ng-init="navigation.charts = false"
ng-click="$event.preventDefault(); click('charts')">
You can actually add href="javascript:void(0)"
<ul>
<li ng-click="click('charts')">
<a href="javascript:void(0)">
<i class="fa fa-bar-chart-o fa-fw"></i>
Charts {{ navigation.charts }}
<span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level"
ng-show="navigation.charts">
<li>
Charts
</li>
<li>
Graphs
</li>
</ul>
This actually happens as you put href="#" which I think refresh the page.

$index restart each row in ng-repeat

I want to repeat this code for each element in my array:
<div class="container" ng-init="parentIndex = $index" ng-repeat="urn in apsocket.mensajes | filter:searchTextURN">
<button style="width:100%" type="button" class="btn btn-info" data-toggle="collapse" data-target="{{'#urn_'+$index}}">{{urn.urn }}</button>
<div id="{{'urn_'+$index}}" class="collapse">
{{urn.timestamp}}
<br>
<p>
<div align="right" ng-repeat="meas in urn.measurements track by $index">
<button style="width:90%;background-color: #68ec6a;border-color:#8bf48c;" type="button" class="btn btn-success" data-toggle="collapse" data-target="{{'#meas_'+parentIndex + '_' +$index}}">{{meas.phenomenon}} </button>
<div style="width:90%" id="{{'meas_'+parentIndex + '_' +$index}}" class="collapse">
{{meas.value + ' ' + meas.uom}}
</div>
</div>
</p>
</div>
</div>
But, while first button in each row works fine and creates a working collapsible, the inner ng-repeats seem not.
Each inner element in each outter row, have the same id. So, for each "container", parentIndex is the same and starts in 0.
What should I do in this case? This is not a fixed array which I load at the beggining. This array recevies data from socket and it get bigger each time a message is received.
If you need any more code or so, just ask.
I would recommend just using the pure angular way. In a repeat, each item has it's own scope so you can do an ng-click="collapse = ! collapse" (something like that), I made you an example here
http://jsfiddle.net/X8era/82/
I just made a fake data structure for examples sake
<ul>
<li ng-repeat="item in objs" ng-click="collapse = ! collapse">
{{item.id}}
<ul ng-show="item.more.length > 0 && collapse">
<li ng-repeat="child in item.more" ng-click="collapse = ! collapse; $event.stopPropagation();" >
{{child.id}}
<ul ng-show="child.more.length > 0 && collapse">
<li ng-repeat="baby in child.more">
{{baby.id}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
If you would like to use the collapse class for an animation or whatever, you can change the part of the ng-show that is collapse to
ng-class="{ 'collapse' : collapse }"
The first 'collapse' being whatever class you want to be toggled.
You don't have to use ng-init="parentIndex = $index". You can access to parent $index like this $parent.$index.
Each ng-repeat creates new scope, that's why you can access to parent by using $parent keyword.
Demo:
var app = angular.module('app',[]);
app.controller('ctrl', function($scope) {
$scope.items = [0, 1, 2, 3, 4];
});
<div ng-app="app" ng-controller="ctrl">
<ul>
<li ng-repeat="item in items track by $index">
<ul>
<li ng-repeat="item in items track by $index">
parent: {{$parent.$index}}
current: {{$index}}
</li>
</ul>
</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

The angularjs tab don't switch?

why the tab don't switch? when i click the tab 2 or other,it seems to do nothing.
<div class="container">
<h1>Bootstrap AngularJS Tabs</h1>
<div ng-app="">
<div ng-init="names = [{name:'one'}, {name:'two'}, {name:'three'}, {name:'four'}, {name:'five'}]">
<ul class="nav nav-tabs">
<li ng-repeat="name in names" ng-class="{active: $index == 0}">
Tab {{$index + 1}}
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade in" id="tab{{$index + 1}}" ng-repeat="name in names" ng-class="{active: $index == 0}">
<span>{{$index + 1}}</span><span>{{$index+2}}</span>
</div>
</div>
</div>
</div>
</div><!--/container-->
<script src="./angular.min.js"></script>
<script src="./bootstrap.min.js"></script>
It's because you're always setting the first tab to active by doing ng-class="{active: $index == 0}". You need to compare $index to a property on the scope which you change when the user clicks on the tab header (by combining both the href on your anchor, and an ng-click). Something like this simplified version: http://jsbin.com/tesosisi/1/edit
That example sets $scope.names.activeIndex = 0; in the controller, but you'd want to inspect the current location hash to see which tab should be active from the start.

Angular ng-repeat element count

<li ng-repeat="Item in Items">
<div ng-switch="($index)==0">
<div ng-switch-when="true">
< Previous
</div>
<div ng-switch-when="false">
{{$index}}
</div>
</div>
</li>
I want to get element count of the Items and want to show "Next >" for last item
Something like this
<li ng-repeat="Item in Items">
<a ng-if="$first" href="#">< Previous</a>
<a ng-if="!$first && !$last" href="#">{{$index}}</a>
<a ng-if="$last" href="#">Next ></a>
</li>
To get the length use Items.length. It becomes more complex if there is a filter. See this SO post

Angular UI Drop-down box inserting line break

Folks,
In using the drop-down toggle of ui.bootstrap .. the component is adding a new line to my menubar instead of falling in line.
I have created a plunker for the same here. As you will see that between button3 and button 4 I have insert a dropdown toggle which breaks the menubar and goes to the next line.
http://plnkr.co/edit/gist:3662702
Any clue as to how I can avoid this ?
I am also placing the code below:
in html file:
<body ng-controller="MainCtrl">
<div class='btn btn-small' >Button1</div>
<div class='btn btn-small' >Button2</div>
<div class='btn btn-small' >Button3</div>
<ul class="dropdown">
<a class="dropdown-toggle">Drop-down menu</a>
<ul class="dropdown-menu">
<li ng-repeat="c in collection">
<a>{{c.name}}</a>
</li>
<li class="divider"></li>
</ul>
</ul>
<div class='btn btn-small' >Button4</div>
</body>
In js file:
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('MainCtrl', function($scope) {
$scope.collection = [{"name":"Angular"},{"name":"Bootstrap"}];
});
Ok so your issue comes from the ul tag (the one with css class dropdown). In your case you should write something like :
<div class='btn btn-small' >Button3</div>
<span class="dropdown">
<a class="dropdown-toggle">Drop-down menu</a>
<ul class="dropdown-menu">
<li ng-repeat="c in collection">
<a>{{c.name}}</a>
</li>
<li class="divider"></li>
</ul>
</span>
<div class='btn btn-small' >Button4</div>
Note how I replace the ul tag by a span one. By default the ul tag have a css property display set to block causing the line break. With the span tag the display is set to inline ensuring that the line will not break.
See the forked plunker : http://plnkr.co/edit/zKeIJczttqBUzO9OchJy

Resources