Call function multiple times with different attributes - angularjs

Hi I'm relatively new in angularjs and I try to create dice roller app.
I have controller with 3 functions ($scope.rollDice, $scope.markDice, $scope.checkMarkedDice). I want to use $scope.rollDice multiple times with different attributes - independently. I would like to know how to modify them to work on some OOP approach. Not sure about the them. In my case if I hit button Roll 4d6 in 1st row, 2nd row is also affected and vice versa.
I guess I need to transfer my rollerDice function to factory or maybe directive. But I'm not sure how to manage it.
I can imagine to transfer $scope.checkMarkedDice to be var function of $scope.rollDice but I don't know how to handle $scope.markDice which has to be call from index.html so it need to be $scope or not?
Plunker

Generally AngularJS is not OOP, therefore you should store individual objects in the arrays and refer to them with index.
I have made what you have requested. (Warning: Heavy Snippet, here is a Plunker instead)
(function() {
'use strict';
var app = angular.module('myApp', []);
app.controller('myCtrl', ["$scope", function($scope) {
$scope.dice_ = [
[1, 6, 4],
[1, 6, 2]
];
$scope.result = [
[],
[]
]; // SPECIFY SIZE / LENGTH HERE (currently: 2 items)
// Roll the dice
$scope.rollDice = function(min, max, count, index) {
var i = 0,
result = [],
markedDice = $scope.checkMarkedDice(index);
if (markedDice.length === 0) {
while (i < count) {
result[i] = {
number: Math.floor(Math.random() * (max - min + 1)) + min,
class: "dice"
};
i += 1;
}
} else {
while (i < count - markedDice.length) {
result[i] = {
number: Math.floor(Math.random() * (max - min + 1)) + min,
class: "dice"
};
i += 1;
}
angular.forEach(markedDice, function(dice) {
result.splice(dice.index, 0, dice);
});
}
$scope.result[index] = result;
};
// Mark the dice
$scope.markDice = function(dice) {
if (dice.class === "dice") {
dice.class = "dice marked";
} else {
dice.class = "dice";
}
};
// Chceck if any dice is marked
$scope.checkMarkedDice = function(index) {
var marked = [];
angular.forEach($scope.result[index], function(dice, $index) {
if (dice.class.indexOf('marked') > -1) {
dice.index = $index;
marked.push(dice);
}
});
return marked;
};
$scope.addDice = function(min, max, count) {
$scope.result.push([]);
$scope.dice_.push([min, max, count]);
}
$scope.removeDice = function() {
$scope.result.pop();
$scope.dice_.pop();
}
}]);
}());
.dice {
display: flex;
justify-content: center;
align-content: center;
flex-direction: column;
float: left;
width: 46px;
color: white;
font-size: 24px;
font-weight: bold;
height: 46px;
border: 1px solid #585858;
border-radius: 15px;
text-align: center;
margin-right: 10px;
background-color: #4573b9;
}
.dice:hover {
background-color: #4573b9bd;
cursor: pointer;
}
.marked {
background: #00466f !important;
}
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="app.js"></script>
<link rel="stylesheet" href="style.css">
<title>Test freez reroller</title>
</head>
<body ng-controller="myCtrl">
<div class="container">
<h2>Basic Table</h2>
<table class="table">
<thead>
<tr class="flex-row">
<th class="col-md-3">Type</th>
<th class="col-md-3">Action</th>
<th class="col-md-6">Result</th>
</tr>
</thead>
<tbody>
<tr class="flex-row" ng-repeat="d_ in dice_ track by $index">
<td>Lorem ipsum</td>
<td>
<button type="button" class="btn btn-primary" ng-click="rollDice(d_[0],d_[1],d_[2],$index);">Roll {{d_[2]}}d{{d_[1]}}</button>
</td>
<td>
<div ng-click="markDice(dice);" class="{{dice.class}}" ng-repeat="dice in result[$index] track by $index">{{dice.number}}</div>
</td>
</tr>
</tbody>
</table>
1: <input type="number" ng-model="a1"><br> 2: <input type="number" ng-model="a2"><br> 3: <input type="number" ng-model="a3"><br>
<button type="button" class="btn btn-success" ng-click="addDice(a1,a2,a3)">Add</button>
<button type="button" class="btn btn-danger" ng-click="removeDice()">Remove</button>
</div>
</body>
</html>

Related

Angular: show content only when any value is entered in the input box

I'm new to Angular. I'm using 1.7.7 version.
What I'm looking for is this:
I have an input box and whenever the user enter any value in it, then only I want to display the table, else not. Also, when the input box becomes empty again, I want to hide the table again. Please refer to the code snippet below for better understanding. Please, let me know if anything is unclear. Thanks in advance!
const app = angular.module('grad-table', []);
app.controller('mainCtrl', function($scope) {
$scope.dimen;
$scope.n = 10;
$scope.max = 100;
/* $scope.getNum = function(){
arr = [];
for(i = 2 ; i <= $scope.max; i++) {
arr.push(i);
}
//console.log(arr);
return arr;
}(); */
$scope.getColName = function() {
arr = [];
for (i = 1; i <= $scope.dimen; i++) {
j = Math.floor(i / 26); // used to calculate first Alphabet in two letter column name
if (i <= 26) {
arr.push(String.fromCharCode(64 + i)); // For A-Z one character
} else if (i % 26 == 0) {
arr.push(String.fromCharCode(64 + j - 1, 64 + (i - 26 * (j - 1)))); // For last Z in two character
} else {
arr.push(String.fromCharCode(64 + j, 64 + (i - 26 * j)));
}
}
//console.log(arr);
return arr;
};
$scope.getRow = function() {
arr = [];
for (i = 1; i <= $scope.dimen; i++) {
arr.push(i);
}
//console.log(arr);
return arr;
};
$scope.getColNum = function() {
arr = [];
for (i = 1; i <= $scope.dimen; i++) {
arr.push(i);
}
return arr;
};
$scope.showTable = true;
$scope.showHide = function() {
console.log("function is called");
if ($scope.dimen != null) {
$scope.showTable = true;
}
};
console.log($scope.showTable);
});
body {
font-family: "Arial";
}
.selectDimen {
margin-bottom: 20px;
}
#grid,
#grid td,
#grid th {
border: 1px solid #a03232;
}
#grid {
border-collapse: collapse;
font-size: 10px;
}
#grid td {
height: 20px;
width: 20px;
}
.rowNum {
text-align: center;
font-weight: bold;
}
.cellNum {
color: #984444;
text-align: right;
font-size: 8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="grad-table">
<head>
<title>Page Title</title>
</head>
<body ng-controller="mainCtrl">
<h1 class="title">Gradient Table</h1>
<form class="selectDimen">
Select Dimensions (2-100):<br>
<input type="number" ng-model="dimen" value="" min="2" max="100" (input)="showHide()" />
</form>
<table ng-show={{showTable}} id="grid">
<tr>
<td class="empty cell"></td>
<th ng-repeat="c in getColName()">{{c}}</th>
</tr>
<tr ng-repeat="r in getRow()">
<td class="rowNum">{{r}}</td>
<td class="cellNum" style="background-color:rgba(255,0,0,{{ ((r+c) - 2) / (2*dimen - 2) }});" ng-repeat="c in getColNum()">{{r + c}}</td>
</tr>
</table>
</body>
</html>
Basically you just need to change
<table ng-show={{showTable}} id="grid">
To
<table ng-if="dimen" id="grid">
The reason is that you bind the model to dimen here:
<input type="number" ng-model="dimen" value="" min="2" max="100" (input)="showHide()" />
And if the value of the input doesn't comply to the validation (min="2" max="100") then angularjs will NOT bind any value to dimen - It will be undefined which will remove the table from the DOM

ngRepeat strange behaviour when its elements order change

I am learning angularjs and I came across some behaviour that I can't understand. I render a list of items in ng-repeat, each has a button to remove itself from the $scope's array - this works as expected but once I added a sortable to the list strange things started to happen.
Here is the running example showing the issue:
https://embed.plnkr.co/eQWcxZ7p8CcACfk6Z53X/
In the example - if I move [^] item 4 (Rocket Launcher) to position 1 and use Rocket Launcher's delete [X] button the list gets updated (i.e. item 4 - Rocket Launcher - that was on position 1 is removed) but the other items delete buttons stop working. Basically moving items and deleting them somehow break the bindings (?).
The code:
(function() {
'use strict';
var app = angular.module('myApp', []);
app.controller('myAppController', function($scope) {
$scope.boxes = [];
$scope.removeBoxItem = function(box, item) {
console.log('Removing "' + item.name + '" form box "' + box.name + '"...');
var index = box.items.indexOf(item);
box.items.splice(index, 1);
console.log(box);
};
this.init = function() {
var e;
e = new Box({
name: 'Red box'
});
$scope.boxes.push(e);
e.items.push(new Item({
index: 1,
name: 'Rock'
}));
e.items.push(new Item({
index: 2,
name: 'Scissors'
}));
e.items.push(new Item({
index: 3,
name: 'Paper'
}));
e.items.push(new Item({
index: 4,
name: 'Rocket launcher'
}));
e = new Box({
name: 'Green box'
});
e.items.push(new Item({
index: 1,
name: 'Chuck the Plant'
}));
e.items.push(new Item({
index: 2,
name: 'Hamster'
}));
e.items.push(new Item({
index: 3,
name: 'Tentacle Chow'
}));
$scope.boxes.push(e);
};
this.init();
});
app.directive("sortable", ["$timeout", function($timeout) {
return {
template: '<div class="sortable" ng-transclude></div>',
transclude: true,
scope: {
'handle': '#'
},
link: function(scope, element, attrs) {
$timeout(function() {
//console.log(element)
var sortable = element.find('> div');
console.log(sortable[0]);
scope.sortable = Sortable.create(sortable[0], {
handle: scope.handle || null
});
});
}
};
}]);
}());
function Box(args) {
this.name = args.name || null;
this.items = [];
}
function Item(args) {
this.index = args.index || null;
this.name = args.name || null;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="style.css" />
<style>
.container {
border: 1px solid #929292;
padding: 5px;
}
.header {
font-size: 1.2rem;
padding: 10px 15px;
background-color: #F5F5F5;
border-bottom: 2px solid #E2E2E2;
}
.body {
background-color: #F2F2F2;
padding: 10px 10px;
margin-bottom: 10px;
}
.body .item {
border: 1px solid #D2D2D2;
padding: 5px;
margin-bottom: 5px;
}
.body .options {
float: right;
}
.body .options .delete {
cursor: pointer;
}
.body .options .handle {
cursor: move;
}
.debug {
margin-top: 20px;
border-top: 1px dotted #929292;
}
</style>
</head>
<body>
<div ng-app="myApp" ng-controller="myAppController as appCtrl">
<div class="container">
<div ng-repeat="box in boxes">
<div class="header">{{ box.name }}</div>
<div class="body">
<div data-sortable="" data-handle=".handle">
<div class="item" ng-repeat="item in box.items">
{{item.index }}) {{ item.name }}
<div class="options">
<span ng-click="removeBoxItem(box, item)" class="delete">[X]</span>
<span class="handle">[^]</span>
</div>
</div>
</div>
</div>
</div>
<div class="debug">
<pre>{{ boxes | json }}
</pre>
</div>
</div>
</div>
<script data-require="jquery#3.1.1" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script data-require="Sortable.js#1.6.0" data-semver="1.6.0" src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.6.0/Sortable.js"></script>
<script data-require="angular.js#1.6.6" data-semver="1.6.6" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.js"></script>
<script src="script.js"></script>
</body>
</html>
I am confused by this, in my real code things get even more broken - I made a collapsible directive that surrounds the "Boxes" so I can open and manipulate one at a time - in that case moving item 4 to position 1 and deleting it removes all items from the view (but not from the $scope). Than adding new item to the $scope's array causes items to correctly reappear. For now I created simpler version as I guess this is all somehow connected.
I am aware the sortable should set the objects indexes etc but for now I'd like to understand what is happening. I suspect I have some issues with understanding what is going on with scopes (?). Would be grateful for any help.

adding a cell to table using add button

I am trying to make a Dynamic table in Angular.js, in which the user inputs number of columns, in a text box provided. Then add buttons are provided under each column to add as much cells as user wants. The cell will only be added to that column only.
I am using ng-repeat to repeat the number of columns and add buttons.
I am able to get the response of the user in a variable, ie, the column under which the user wants to add the cell.
Can someone please give me a controller to add a cell to the selected column either by using ng-repeat , ng-model or without it.
my table code looks somewhat like this:
<table>
<tr>
<th ng-repeat="n in arr track by $index">SET {{n.setalpha}} </th><!--table heading, dont mind this-->
</tr>
<tr ng-repeat="<!--something goes here-->">
<!--<select ng-model="name" ng-options="options.topicname for options in topics"></select>-->
</tr>
<tr>
<td ng-repeat="n in arr track by $index">
<button ng-click="addSelected($index+1)">add{{$index+1}}</button>
</td>
</tr>
</table>
where: n in arr track by $index , is used to repeat the table heading and add button say 'n' number of times and addSelected($index+1) is a function whose controller is:
$scope.addSelected = function (setno) {
console.log(setno);
$scope.thisset = setno;
}
, $scope.thisset is the variable in which i have the response of the user, ie, the column under which the user wants to add a cell.
NOTE: I want to add the cell in column only under which the user wants. NOT in all columns. MY CODE:
var app = angular.module('topicSelector', []);
app.controller('topicController', function ($scope) {
$scope.arr = [];
$scope.thisset = -1; //tells in which set, cell has to added.
$scope.topics = [
{
topicid: "1",
topicname: "history"
},
{
topicid: "2",
topicname: "geography"
},
{
topicid: "3",
topicname: "maths"
}
];
$scope.DefineSets = function () {
for (var i = 1; i <= $scope.no_of_sets; i++) {
$scope.arr.push({
setno: i,
setalpha: String.fromCharCode(64 + i)
});
};
};
$scope.addSelected = function (setno) {
console.log(setno);
$scope.thisset = setno;
}
});
table {
width: 100%;
}
<!doctype html>
<html ng-app="topicSelector">
<head>
<title>
topic selector
</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="app.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h3>Enter number of sets:</h3>
<div ng-controller="topicController">
<form ng-submit="DefineSets()">
<input type="text" ng-model="no_of_sets" placeholder="number of sets" name="no_of_sets">
<button>Submit</button>
</form>
<br>
<br>
<table>
<tr>
<th ng-repeat="n in arr track by $index">SET {{n.setalpha}} </th>
</tr>
<!--<tr ng-repeat="">
<select ng-model="name" ng-options="options.topicname for options in topics"></select>
</tr>-->
<tr>
<td ng-repeat="n in arr track by $index">
<button ng-click="addSelected($index+1)">add{{$index+1}}</button>
</td>
</tr>
</table>
</div>
</body>
</html>
LINK TO PLUNK PLUNK
In the following example I used lists instead of tables with fle display, IMHO it is a better approach:
(function (angular) {
"use strict";
function GrowController ($log) {
var vm = this;
vm.cols = [];
vm.size = 0;
vm.sizeChanged = function () {
var size = vm.size, cols = vm.cols,
diff = size - cols.length;
$log.debug("Size changed to", size, cols);
if (diff > 0) {
for (var i = 0; i < diff; i++) {
cols.push([]);
}
} else {
cols.splice(diff, -diff);
}
};
vm.addCell = function (index) {
var cols = vm.cols;
$log.debug("Cell added in column", index);
cols[index].push(index + "." + cols[index].length);
};
}
angular.module("app",[])
.controller("GrowController", ["$log", GrowController]);
}(angular));
ul {
list-style: none;
padding: 0;
margin: 0;
}
.cols {
display: flex;
}
.cells {
display: flex;
flex-direction: column;
}
button.add-cell {
display: block;
}
<div ng-controller="GrowController as $ctrl" ng-app="app" ng-strict-di>
<p>
<label for="size">Number of columns(0-10):</label>
<input id="size" type="number" ng-model="$ctrl.size" ng-change="$ctrl.sizeChanged()" min="0" max="10">
</p>
<ul class="cols" ng-if="$ctrl.cols.length">
<li ng-repeat="col in $ctrl.cols">
<button class="add-cell-button" ng-click="$ctrl.addCell($index)">Add cell</button>
<ul class="cells" ng-if="col.length">
<li ng-repeat="cell in col">{{ ::cell }}</li>
</ul>
</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
Anyway, I Angularjs 1.5.6 you should consider using "Components" instead of "Controllers" and "one-side" bindings.

angular dragdrop (using jQuery UI) - disable swapping

I have problem with swapping the dragged/dropped elements.
DOM / Angular Structure:
angular.module('app', ['ngDragDrop'])
.controller('controller', function($scope) {
$scope.listItems = [
{name: "some name", title: "title"},
{name: "some name2", title: "title2"},
];
$scope.input = {};
$scope.draggableOprions = {
revert: 'invalid'
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="https://code.angularjs.org/1.4.9/angular.js"></script>
<script src="https://cdn.jsdelivr.net/angular.dragdrop/1.07/angular-dragdrop.min.js"></script>
<div ng-app="app">
<div ng-controller="controller">
<div class="container">
<ul>
<li data-drag="true"
data-jqyoui-options="draggableOprions"
jqyoui-draggable="{animate:true}"
ng-model="item" ng-repeat="item in listItems track by $index">
{{item.title}}
</li>
</ul>
</div>
<div class="container"
data-drop="true"
data-jqyoui-options jqyoui-droppable
ng-model="input">
<input ng-model="input.name">
</div>
</div>
</div>
The problem:
While I drag and drop an list item 1 - the name property of the list item 1 comes to the input model. But no longer is available in list item 1. Actually the list item 1 value goes undefined || null after I drop it in the input. If I now try to drag-n-drop list item 2 item in the input - the values swapping (list item 1 = undefined || null ? and list item 2 = list item 1 value and input model equal to list item 2 value`. So everything shuffle.
What I need:
I need to drag and drop list items in the input, avoiding losing values in list items. Every time i drop list item in the input, I need it's value to bind to the input.
Out of the box
I can change the drag and drop library, or even use source code, but the library is the better choice. I accept almost every good working answer which didn't broke any standards of good code (I mean that I need code which will not broke the other code and has good structure).
I suggest to use ngDraggable, an Angular module with no depency from jQuery or jQuery-ui.
Here below is a working snippet or check my Codepen:
angular.module('app', ['ngDraggable'])
.controller('controller', function($scope) {
$scope.listItems = [{
name: "some name",
title: "title1"
}, {
name: "some name2",
title: "title2"
}, {
name: "some name3",
title: "title3"
}, ];
$scope.droppedObjects = [];
$scope.input = {};
// drag complete over drop area
$scope.onDragComplete = function(data, evt) {
console.log("drag success, data:", data);
var index = $scope.droppedObjects.indexOf(data);
if (index > -1) {
$scope.droppedObjects.splice(index, 1);
}
}
// drop complete over drop area
$scope.onDropComplete = function(data, evt) {
console.log("drop success, data:", data);
var index = $scope.droppedObjects.indexOf(data);
if (index == -1)
$scope.droppedObjects.push(data);
}
// drop complete over input box
$scope.onDropCompleteInput = function(data, evt) {
console.log("drop on input success, data:", data);
$scope.input = data;
}
// drop complete over items area (remove from dropped list)
$scope.onDropCompleteRemove = function(data, evt) {
console.log("drop success - remove, data:", data);
var index = $scope.droppedObjects.indexOf(data);
if (index != -1)
$scope.droppedObjects.splice(index);
}
// other draggable events handlers
var onDraggableEvent = function(evt, data) {
console.log("128", "onDraggableEvent", evt, data);
}
$scope.$on('draggable:start', onDraggableEvent);
//$scope.$on('draggable:move', onDraggableEvent);
$scope.$on('draggable:end', onDraggableEvent);
});
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
[ng-drag] {
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.item {
width: 100px;
height: 60px;
background: rgba(255, 0, 0, 0.5);
color: white;
text-align: center;
padding-top: 5%;
display: inline-block;
margin: 0 10px;
cursor: move;
}
ul.draggable-objects:after {
display: block;
content: "";
clear: both;
}
.draggable-objects li {
float: left;
display: block;
width: 120px;
height: 100px;
}
[ng-drag].drag-over {
border: solid 1px red;
}
[ng-drag].dragging {
opacity: 0.5;
}
.drop-container {
background: rgba(0, 255, 0, 0.5);
text-align: center;
width: 600px;
height: 200px;
padding-top: 90px;
display: block;
margin: 20px auto;
position: relative;
}
.drop-input {
width: 200px;
height: 40px;
}
.drag-enter {
border: solid 5px red;
}
.drop-container span.title {
display: block;
position: absolute;
top: 10%;
left: 50%;
width: 200px;
height: 20px;
margin-left: -100px;
margin-top: -10px;
}
.drop-container div {
position: relative;
z-index: 2;
}
<script src="//code.angularjs.org/1.4.8/angular.js"></script>
<script src="//rawgit.com/fatlinesofcode/ngDraggable/master/ngDraggable.js"></script>
<body ng-app="app">
<div ng-controller="controller">
<div class="row">
<h1>ngDraggable Example</h1>
</div>
<div ng-drop="true" ng-drop-success="onDropCompleteRemove($data,$event)">
<ul class="draggable-objects">
<li ng-repeat="obj in listItems">
<div ng-drag="true" ng-drag-data="obj" data-allow-transform="true" class="item"> {{obj.title}} </div>
</li>
</ul>
</div>
<hr/>
<div ng-drop="true" ng-drop-success="onDropComplete($data,$event)" class="drop-container">
<span class="title">Drop area</span>
<div ng-repeat="obj in droppedObjects" ng-drag="true" ng-drag-data="obj" ng-drag-success="onDragComplete($data,$event)" class="item">
{{obj.title}}
</div>
</div>
<hr/>
<div class="container">
Drop on input:
<input ng-model="input.name" class="drop-input" ng-drop="true" ng-drop-success="onDropCompleteInput($data,$event)">
</div>
<br>
<hr/>
<pre>listItems = {{listItems|json}}</pre>
<pre>input = {{input|json}}</pre>
<pre>droppedObjects = {{droppedObjects|json}}</pre>
</div>
</body>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="https://code.angularjs.org/1.4.9/angular.js"></script>
<script src="https://cdn.jsdelivr.net/angular.dragdrop/1.07/angular-dragdrop.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="MyController">
<div id="products">
<h1 class="ui-widget-header">Products</h1>
<div id="catalog">
<div>
<ul>
<li ng-repeat='item in list1' ng-show="item.title" data-drag="true" data-jqyoui-options="{revert: 'invalid', helper: 'clone'}" ng-model="list1" jqyoui-draggable="{index: {{$index}}, animate: true, placeholder: 'keep'}">{{item.title}}</li>
</ul>
</div>
</div>
</div>
<div id="cart">
<h1 class="ui-widget-header">Shopping Cart</h1>
<div class="ui-widget-content">
<ol data-drop="true" ng-model='list4' jqyoui-droppable="{multiple:true}">
<li ng-repeat="item in list4 track by $index" ng-show="item.title" data-drag="true" data-jqyoui-options="{revert: 'invalid', helper: 'clone'}" ng-model="list4" jqyoui-draggable="{index: {{$index}},animate:true}">{{item.title}}</li>
<li class="placeholder" ng-hide="hideMe()">Add your items here</li>
</ol>
</div>
</div>
</div>
<script>
var app = angular.module('myApp', ['ngDragDrop']);
app.controller('MyController', function ($scope,$http,$sce)
{
$scope.list1 = [{'title': 'Lolcat Shirt'},{'title': 'Cheezeburger Shirt'},{'title': 'Buckit Shirt'}];
$scope.list4 = [];
$scope.hideMe = function()
{
return $scope.list4.length > 0;
}
});
</script>
</body>
</html>
You have to use helper: 'clone' in data-jqyoui-options

How to do paging in AngularJS?

I have a dataset of about 1000 items in-memory and am attempting to create a pager for
this dataset, but I'm not sure on how to do this.
I'm using a custom filter function to filter the results, and that works fine, but somehow I need to get the number of pages out.
Any clues?
Angular UI Bootstrap - Pagination Directive
Check out UI Bootstrap's pagination directive. I ended up using it rather than what is posted here as it has enough features for my current use and has a thorough test spec to accompany it.
View
<!-- table here -->
<pagination
ng-model="currentPage"
total-items="todos.length"
max-size="maxSize"
boundary-links="true">
</pagination>
<!-- items/page select here if you like -->
Controller
todos.controller("TodoController", function($scope) {
$scope.filteredTodos = []
,$scope.currentPage = 1
,$scope.numPerPage = 10
,$scope.maxSize = 5;
$scope.makeTodos = function() {
$scope.todos = [];
for (i=1;i<=1000;i++) {
$scope.todos.push({ text:"todo "+i, done:false});
}
};
$scope.makeTodos();
$scope.$watch("currentPage + numPerPage", function() {
var begin = (($scope.currentPage - 1) * $scope.numPerPage)
, end = begin + $scope.numPerPage;
$scope.filteredTodos = $scope.todos.slice(begin, end);
});
});
I have made a working plunker for reference.
Legacy Version:
View
<!-- table here -->
<div data-pagination="" data-num-pages="numPages()"
data-current-page="currentPage" data-max-size="maxSize"
data-boundary-links="true"></div>
<!-- items/page select here if you like -->
Controller
todos.controller("TodoController", function($scope) {
$scope.filteredTodos = []
,$scope.currentPage = 1
,$scope.numPerPage = 10
,$scope.maxSize = 5;
$scope.makeTodos = function() {
$scope.todos = [];
for (i=1;i<=1000;i++) {
$scope.todos.push({ text:"todo "+i, done:false});
}
};
$scope.makeTodos();
$scope.numPages = function () {
return Math.ceil($scope.todos.length / $scope.numPerPage);
};
$scope.$watch("currentPage + numPerPage", function() {
var begin = (($scope.currentPage - 1) * $scope.numPerPage)
, end = begin + $scope.numPerPage;
$scope.filteredTodos = $scope.todos.slice(begin, end);
});
});
I have made a working plunker for reference.
I recently implemented paging for the Built with Angular site. You chan checkout the source: https://github.com/angular/builtwith.angularjs.org
I'd avoid using a filter to separate the pages. You should break up the items into pages within the controller.
I've had to implement pagination quite a few times with Angular, and it was always a bit of a pain for something that I felt could be simplified. I've used some of the ideas presented here and elsewhere to make a pagination module that makes pagination as simple as:
<ul>
<li dir-paginate="item in items | itemsPerPage: 10">{{ item }}</li>
</ul>
// then somewhere else on the page ....
<dir-pagination-controls></dir-pagination-controls>
That's it. It has the following features:
No custom code needed in your controller to tie the collection items to the pagination links.
You aren't bound to using a table or gridview - you can paginate anything you can ng-repeat!
Delegates to ng-repeat, so you can use any expression that could be validly used in an ng-repeat, including filtering, ordering etc.
Works across controllers - the pagination-controls directive does not need to know anything about the context in which the paginate directive is called.
Demo : http://plnkr.co/edit/Wtkv71LIqUR4OhzhgpqL?p=preview
For those who are looking for a "plug and play" solution, I think you'll find this useful.
Code
The code is available here on GitHub and includes a pretty good set of tests:
https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
If you are interested I also wrote a short piece with a little more insight into the design of the module: http://www.michaelbromley.co.uk/blog/108/paginate-almost-anything-in-angularjs/
I just made a JSFiddle that show pagination + search + order by on each column using btford code: http://jsfiddle.net/SAWsA/11/
I updated Scotty.NET's plunkr http://plnkr.co/edit/FUeWwDu0XzO51lyLAEIA?p=preview so that it uses newer versions of angular, angular-ui, and bootstrap.
Controller
var todos = angular.module('todos', ['ui.bootstrap']);
todos.controller('TodoController', function($scope) {
$scope.filteredTodos = [];
$scope.itemsPerPage = 30;
$scope.currentPage = 4;
$scope.makeTodos = function() {
$scope.todos = [];
for (i=1;i<=1000;i++) {
$scope.todos.push({ text:'todo '+i, done:false});
}
};
$scope.figureOutTodosToDisplay = function() {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage);
var end = begin + $scope.itemsPerPage;
$scope.filteredTodos = $scope.todos.slice(begin, end);
};
$scope.makeTodos();
$scope.figureOutTodosToDisplay();
$scope.pageChanged = function() {
$scope.figureOutTodosToDisplay();
};
});
Bootstrap UI component
<pagination boundary-links="true"
max-size="3"
items-per-page="itemsPerPage"
total-items="todos.length"
ng-model="currentPage"
ng-change="pageChanged()"></pagination>
This is a pure javascript solution that I've wrapped as an Angular service to implement pagination logic like in google search results.
Working demo on CodePen at http://codepen.io/cornflourblue/pen/KVeaQL/
Details and explanation at this blog post
function PagerService() {
// service definition
var service = {};
service.GetPager = GetPager;
return service;
// service implementation
function GetPager(totalItems, currentPage, pageSize) {
// default to first page
currentPage = currentPage || 1;
// default page size is 10
pageSize = pageSize || 10;
// calculate total pages
var totalPages = Math.ceil(totalItems / pageSize);
var startPage, endPage;
if (totalPages <= 10) {
// less than 10 total pages so show all
startPage = 1;
endPage = totalPages;
} else {
// more than 10 total pages so calculate start and end pages
if (currentPage <= 6) {
startPage = 1;
endPage = 10;
} else if (currentPage + 4 >= totalPages) {
startPage = totalPages - 9;
endPage = totalPages;
} else {
startPage = currentPage - 5;
endPage = currentPage + 4;
}
}
// calculate start and end item indexes
var startIndex = (currentPage - 1) * pageSize;
var endIndex = startIndex + pageSize;
// create an array of pages to ng-repeat in the pager control
var pages = _.range(startPage, endPage + 1);
// return object with all pager properties required by the view
return {
totalItems: totalItems,
currentPage: currentPage,
pageSize: pageSize,
totalPages: totalPages,
startPage: startPage,
endPage: endPage,
startIndex: startIndex,
endIndex: endIndex,
pages: pages
};
}
}
Below solution quite simple.
<pagination
total-items="totalItems"
items-per-page= "itemsPerPage"
ng-model="currentPage"
class="pagination-sm">
</pagination>
<tr ng-repeat="country in countries.slice((currentPage -1) * itemsPerPage, currentPage * itemsPerPage) ">
Here is sample jsfiddle
I've extracted the relevant bits here. This is a 'no frills' tabular pager, so sorting or filtering is not included. Feel free to change/add as needed:
//your data source may be different. the following line is
//just for demonstration purposes only
var modelData = [{
text: 'Test1'
}, {
text: 'Test2'
}, {
text: 'Test3'
}];
(function(util) {
util.PAGE_SIZE = 10;
util.range = function(start, end) {
var rng = [];
if (!end) {
end = start;
start = 0;
}
for (var i = start; i < end; i++)
rng.push(i);
return rng;
};
util.Pager = function(data) {
var self = this,
_size = util.PAGE_SIZE;;
self.current = 0;
self.content = function(index) {
var start = index * self.size,
end = (index * self.size + self.size) > data.length ? data.length : (index * self.size + self.size);
return data.slice(start, end);
};
self.next = function() {
if (!self.canPage('Next')) return;
self.current++;
};
self.prev = function() {
if (!self.canPage('Prev')) return;
self.current--;
};
self.canPage = function(dir) {
if (dir === 'Next') return self.current < self.count - 1;
if (dir === 'Prev') return self.current > 0;
return false;
};
self.list = function() {
var start, end;
start = self.current < 5 ? 0 : self.current - 5;
end = self.count - self.current < 5 ? self.count : self.current + 5;
return Util.range(start, end);
};
Object.defineProperty(self, 'size', {
configurable: false,
enumerable: false,
get: function() {
return _size;
},
set: function(val) {
_size = val || _size;
}
});
Object.defineProperty(self, 'count', {
configurable: false,
enumerable: false,
get: function() {
return Math.ceil(data.length / self.size);
}
});
};
})(window.Util = window.Util || {});
(function(ns) {
ns.SampleController = function($scope, $window) {
$scope.ModelData = modelData;
//instantiate pager with array (i.e. our model)
$scope.pages = new $window.Util.Pager($scope.ModelData);
};
})(window.Controllers = window.Controllers || {});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<table ng-controller="Controllers.SampleController">
<thead>
<tr>
<th>
Col1
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in pages.content(pages.current)" title="{{item.text}}">
<td ng-bind-template="{{item.text}}"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">
«
{{n + 1}}
»
</td>
</tr>
</tfoot>
</table>
The jQuery Mobile angular adapter has a paging filter you could base off of.
Here's a demo fiddle that uses it (add more than 5 items and it becomes paged): http://jsfiddle.net/tigbro/Du2DY/
Here's the source: https://github.com/tigbro/jquery-mobile-angular-adapter/blob/master/src/main/webapp/utils/paging.js
For anyone who find it difficult like me to create a paginator for a table I post this.
So, in your view :
<pagination total-items="total" items-per-page="itemPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
<!-- To specify your choice of items Per Pages-->
<div class="btn-group">
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Left'" data-ng-click="setItems(5)">5</label>
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Middle'" data-ng-click="setItems(10)">10</label>
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Right'" data-ng-click="setItems(15)">15</label>
</div>
//And don't forget in your table:
<tr data-ng-repeat="p in profiles | offset: (currentPage-1)*itemPerPage | limitTo: itemPerPage" >
In your angularJs:
var module = angular.module('myapp',['ui.bootstrap','dialogs']);
module.controller('myController',function($scope,$http){
$scope.total = $scope.mylist.length;
$scope.currentPage = 1;
$scope.itemPerPage = 2;
$scope.start = 0;
$scope.setItems = function(n){
$scope.itemPerPage = n;
};
// In case you can replace ($scope.currentPage - 1) * $scope.itemPerPage in <tr> by "start"
$scope.pageChanged = function() {
$scope.start = ($scope.currentPage - 1) * $scope.itemPerPage;
};
});
//and our filter
module.filter('offset', function() {
return function(input, start) {
start = parseInt(start, 10);
return input.slice(start);
};
});
I use this 3rd party pagination library and it works well. It can do local/remote datasources and it's very configurable.
https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
<dir-pagination-controls
[max-size=""]
[direction-links=""]
[boundary-links=""]
[on-page-change=""]
[pagination-id=""]
[template-url=""]
[auto-hide=""]>
</dir-pagination-controls>
Since Angular 1.4, the limitTo filter also accepts a second optional argument begin
From the docs:
{{ limitTo_expression | limitTo : limit : begin}}
begin
(optional)
string|number
Index at which to begin limitation. As a negative index, begin indicates an offset from the end of input. Defaults to 0.
So you don't need to create a new directive, This argument can be used to set the offset of the pagination
ng-repeat="item in vm.items| limitTo: vm.itemsPerPage: (vm.currentPage-1)*vm.itemsPerPage"
You can easily do this using Bootstrap UI directive.
This answer is a modification of the answer given by #Scotty.NET, I have changed the code because <pagination> directive is deprecated now.
Following code generates the pagination:
<ul uib-pagination
boundary-links="true"
total-items="totalItems"
items-per-page="itemsPerPage"
ng-model="currentPage"
ng-change="pageChanged()"
class="pagination"
previous-text="‹"
next-text="›"
first-text="«"
last-text="»">
</ul>
To make it functional, use this in your controller:
$scope.filteredData = []
$scope.totalItems = $scope.data.length;
$scope.currentPage = 1;
$scope.itemsPerPage = 5;
$scope.setPage = function (pageNo) {
$scope.currentPage = pageNo;
};
$scope.pageChanged = function() {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage)
, end = begin + $scope.itemsPerPage;
$scope.filteredData = $scope.data.slice(begin, end);
};
$scope.pageChanged();
Refer to this for more options of pagination: Bootstrap UI Pagination Directive
ng-repeat pagination
<div ng-app="myApp" ng-controller="MyCtrl">
<input ng-model="q" id="search" class="form-control" placeholder="Filter text">
<select ng-model="pageSize" id="pageSize" class="form-control">
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
</select>
<ul>
<li ng-repeat="item in data | filter:q | startFrom:currentPage*pageSize | limitTo:pageSize">
{{item}}
</li>
</ul>
<button ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1">
Previous
</button>
{{currentPage+1}}/{{numberOfPages()}}
<button ng-disabled="currentPage >= getData().length/pageSize - 1" ng- click="currentPage=currentPage+1">
Next
</button>
</div>
<script>
var app=angular.module('myApp', []);
app.controller('MyCtrl', ['$scope', '$filter', function ($scope, $filter) {
$scope.currentPage = 0;
$scope.pageSize = 10;
$scope.data = [];
$scope.q = '';
$scope.getData = function () {
return $filter('filter')($scope.data, $scope.q)
}
$scope.numberOfPages=function(){
return Math.ceil($scope.getData().length/$scope.pageSize);
}
for (var i=0; i<65; i++) {
$scope.data.push("Item "+i);
}
}]);
app.filter('startFrom', function() {
return function(input, start) {
start = +start; //parse to int
return input.slice(start);
}
});
</script>
Previous messages recommended basically how to build a paging by yourself. If you are like me, and prefer a finished directive, I just found a great one called ngTable. It supports sorting, filtering and pagination.
It is a very clean solution, all you need in your view:
<table ng-table="tableParams" class="table">
<tr ng-repeat="user in $data">
<td data-title="'Name'" sortable="'name'">
{{user.name}}
</td>
<td data-title="'Age'" sortable="'age'">
{{user.age}}
</td>
</tr>
</table>
And in controller:
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
name: 'asc' // initial sorting
}
}, {
total: data.length, // length of data
getData: function($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ?
$filter('orderBy')(data, params.orderBy()) :
data;
var start = (params.page() - 1) * params.count();
var end = params.page() * params.count();
$defer.resolve(orderedData.slice( start, end));
}
});
Link to GitHub: https://github.com/esvit/ng-table/
Angular-Paging
is a wonderful choice
A directive to aid in paging large datasets while requiring the bare minimum of actual paging information. We are very dependant on the server for "filtering" results in this paging scheme. The central idea being we only want to hold the active "page" of items - rather than holding the entire list of items in memory and paging on the client-side.
Old question but since I think my approach is a bit different and less complex I will share this and hope that someone besides me find it useful.
What I found to be an easy and small solution to pagination is to combine a directive with a filter which uses the same scope variables.
To implement this you add the filter on the array and add the directiv like this
<div class="row">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Price</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items | cust_pagination:p_Size:p_Step">
<td>{{item.Name}}</td>
<td>{{item.Price}}</td>
<td>{{item.Quantity}}</td>
</tr>
</tbody>
</table>
<div cust-pagination p-items="items" p-boundarylinks="true" p-size="p_Size" p-step="p_Step"></div>
</div>
p_Size and p_Step are scope variables which can be customized in the scope else the default value of the p_Size is 5 and p_Step is 1.
When a step is change in the pagination the p_Step is updated and will trigger a new filtering by cust_pagination filter.
The cust_pagination filter then slices the array depending on the p_Step value like below and only return the active records selected in the pagination section
var startIndex = nStep * nPageSize;
var endIndex = startIndex + nPageSize;
var arr = items.slice(startIndex, endIndex);
return arr;
DEMO View the complete solution in this plunker
There is my example. Selected button in the middle on the list
Controller.
config >>>
$scope.pagination = {total: null, pages: [], config: {count: 10, page: 1, size: 7}};
Logic for pagination:
/*
Pagination
*/
$scope.$watch('pagination.total', function (total) {
if(!total || total <= $scope.pagination.config.count) return;
_setPaginationPages(total);
});
function _setPaginationPages(total) {
var totalPages = Math.ceil(total / $scope.pagination.config.count);
var pages = [];
var start = $scope.pagination.config.page - Math.floor($scope.pagination.config.size/2);
var finish = null;
if((start + $scope.pagination.config.size - 1) > totalPages){
start = totalPages - $scope.pagination.config.size;
}
if(start <= 0) {
start = 1;
}
finish = start + $scope.pagination.config.size - 1;
if(finish > totalPages){
finish = totalPages;
}
for (var i = start; i <= finish; i++) {
pages.push(i);
}
$scope.pagination.pages = pages;
}
$scope.$watch("pagination.config.page", function(page){
_setPaginationPages($scope.pagination.total);
_getRespondents($scope.pagination.config);
});
and my view on bootstap
<ul ng-class="{hidden: pagination.total == 0}" class="pagination">
<li ng-click="pagination.config.page = pagination.config.page - 1"
ng-class="{disabled: pagination.config.page == 1}" >«</li>
<li ng-repeat="p in pagination.pages"
ng-click="pagination.config.page = p"
ng-class="{active: p == pagination.config.page}">{{p}}</li>
<li ng-click="pagination.config.page = pagination.config.page + 1"
ng-class="{disabled: pagination.config.page == pagination.pages.length}">»</li>
</ul >
It is useful
I wish I could comment, but I'll just have to leave this here:
Scotty.NET's answer and user2176745's redo for later versions are both great, but they both miss something that my version of AngularJS (v1.3.15) breaks on:
i is not defined in $scope.makeTodos.
As such, replacing with this function fixes it for more recent angular versions.
$scope.makeTodos = function() {
var i;
$scope.todos = [];
for (i=1;i<=1000;i++) {
$scope.todos.push({ text:'todo '+i, done:false});
}
};
Overview : Pagination using
- ng-repeat
- uib-pagination
View :
<div class="row">
<div class="col-lg-12">
<table class="table">
<thead style="background-color: #eee">
<tr>
<td>Dispature</td>
<td>Service</td>
<td>Host</td>
<td>Value</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in app.metricsList">
<td>{{x.dispature}}</td>
<td>{{x.service}}</td>
<td>{{x.host}}</td>
<td>{{x.value}}</td>
</tr>
</tbody>
</table>
<div align="center">
<uib-pagination items-per-page="app.itemPerPage" num-pages="numPages"
total-items="app.totalItems" boundary-link-numbers="true"
ng-model="app.currentPage" rotate="false" max-size="app.maxSize"
class="pagination-sm" boundary-links="true"
ng-click="app.getPagableRecords()"></uib-pagination>
<div style="float: right; margin: 15px">
<pre>Page: {{app.currentPage}} / {{numPages}}</pre>
</div>
</div>
</div>
</div>
JS Controller :
app.controller('AllEntryCtrl',['$scope','$http','$timeout','$rootScope', function($scope,$http,$timeout,$rootScope){
var app = this;
app.currentPage = 1;
app.maxSize = 5;
app.itemPerPage = 5;
app.totalItems = 0;
app.countRecords = function() {
$http.get("countRecord")
.success(function(data,status,headers,config){
app.totalItems = data;
})
.error(function(data,status,header,config){
console.log(data);
});
};
app.getPagableRecords = function() {
var param = {
page : app.currentPage,
size : app.itemPerPage
};
$http.get("allRecordPagination",{params : param})
.success(function(data,status,headers,config){
app.metricsList = data.content;
})
.error(function(data,status,header,config){
console.log(data);
});
};
app.countRecords();
app.getPagableRecords();
}]);
I would like to add my solution that works with ngRepeat and filters that you use with it without using a $watch or a sliced array.
Your filter results will be paginated!
var app = angular.module('app', ['ui.bootstrap']);
app.controller('myController', ['$scope', function($scope){
$scope.list= ['a', 'b', 'c', 'd', 'e'];
$scope.pagination = {
currentPage: 1,
numPerPage: 5,
totalItems: 0
};
$scope.searchFilter = function(item) {
//Your filter results will be paginated!
//The pagination will work even with other filters involved
//The total number of items in the result of your filter is accounted for
};
$scope.paginationFilter = function(item, index) {
//Every time the filter is used it restarts the totalItems
if(index === 0)
$scope.pagination.totalItems = 0;
//This holds the totalItems after the filters are applied
$scope.pagination.totalItems++;
if(
index >= (($scope.pagination.currentPage - 1) * $scope.pagination.numPerPage)
&& index < ((($scope.pagination.currentPage - 1) * $scope.pagination.numPerPage) + $scope.pagination.numPerPage)
)
return true; //return true if item index is on the currentPage
return false;
};
}]);
In the HTML make sure that you apply your filters to the ngRepeat before the pagination filter.
<table data-ng-controller="myController">
<tr data-ng-repeat="item in list | filter: searchFilter | filter: paginationFilter track by $index">
<td>
{{item}}
</td>
<tr>
</table>
<ul class="pagination-sm"
uib-pagination
data-boundary-links="true"
data-total-items="pagination.totalItems"
data-items-per-page="pagination.numPerPage"
data-ng-model="pagination.currentPage"
data-previous-text="‹"
data-next-text="›"
data-first-text="«"
data-last-text="»">
</ul>
This below code will help for providing custom paging in backend with angular repeat.
Your data will be in
$scope.myticketIssuesData = [];
$scope.allticketIssuesData = [];
var jiraapp = angular.module('jiraapp', ['ui.bootstrap']);
jiraapp.controller('JiraController', ['$scope', '$http', '$window','$location', function JiraController($scope, $http, $window,$location) {
$scope.myticketIssuesData = [];
$scope.allticketIssuesData = [];
$scope.jiraIssue = {};
$scope.RequesterType = [];
$scope.loading = false;
$scope.showerror = false;
$scope.alert = {};
$scope.maxSize = 10;
$scope.totalCount = 0;
$scope.pageIndex = 0;
$scope.startIndex = 0;
$scope.pageSizeSelected = 10;
$scope.maxallSize = 10;
$scope.totalallCount = 0;
$scope.pageallIndex = 0;
$scope.startallIndex = 0;
$scope.pageallSizeSelected = 10;
$scope.getUserTickets = function() {
$scope.loading = true;
$http({
method: 'GET',
url: 'http://localhost:53583/api/Jira/getUserTickets?assignee='+$scope.loc+'&startAt='+ $scope.startIndex +'&maxResults='+$scope.pageSizeSelected,
headers: {
"Accept": "application/json",
"Access-Control-Allow-Origin": "http://localhost:8080",
"crossDomain": "true",
}
}).then(function successCallback(response) {
$scope.myticketIssuesData = response.data.issues;
$scope.totalCount = response.data.total;
$scope.loading = false;
}, function errorCallback(response) {
$scope.loading = false;
});
}
$scope.getrequestType = function(){
$http({
method: 'GET',
url: 'http://localhost:53583/api/Jira/getrequestType',
headers: {
"Accept": "application/json",
"Access-Control-Allow-Origin": "http://localhost:8080",
"crossDomain": "true",
}
}).then(function successCallback(response) {
$scope.RequesterType = response.data.values;
}, function errorCallback(response) {
});
}
$scope.getDropDown = function(){
$scope.getrequestType();
}
$scope.initialize = function (item) {
$scope.getUserTickets();
$scope.getDropDown();
}
$scope.initialize();
$scope.pageChanged = function () {
if($scope.pageIndex == 0)
$scope.startIndex = 0;
else if($scope.pageIndex == 1)
$scope.startIndex = 0;
else
$scope.startIndex = (($scope.pageIndex-1) * $scope.pageSizeSelected);
$scope.getUserTickets();
};
$scope.pageallChanged = function () {
if($scope.pageallIndex == 0)
$scope.startallIndex = 0;
else if($scope.pageallIndex == 1)
$scope.startallIndex = 0;
else
$scope.startallIndex = (($scope.pageallIndex-1) * $scope.pageallSizeSelected);
$scope.getAllTickets();
};
$scope.changeallPageSize = function () {
$scope.pageallIndex = 0;
$scope.getAllTickets();
};
$scope.getAllTickets = function() {
$scope.loading = true;
$http({
method: 'GET',
url: 'http://localhost:53583/api/Jira/getAllTickets?startAt='+ $scope.startallIndex +'&maxResults='+$scope.pageallSizeSelected,
headers: {
"Accept": "application/json",
"Access-Control-Allow-Origin": "http://localhost:8080",
"crossDomain": "true",
}
}).then(function successCallback(response) {
$scope.allticketIssuesData = response.data.issues;
$scope.totalallCount = response.data.total;
$scope.loading = false;
}, function errorCallback(response) {
$scope.loading = false;
});
}
}]);
<html ng-app="jiraapp">
<head>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js"
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous">
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro' rel='stylesheet' type='text/css'>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
crossorigin="anonymous"></script>
<script src="/angular.min.js"></script>
<script src="/jira.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular-route.min.js"></script>
<script src="/ui-bootstrap-tpls-0.13.4.min.js"></script>
<!-- this is important -->
<style type="text/css">
#loading {
position: fixed;
top: 50%;
left: 50%;
margin-top: -5em;
margin-left: -10em;
}
.pagination {
display: inline-block;
padding-left: 0;
margin: 20px 0;
border-radius: 4px
}
.pagination>li {
display: inline
}
.pagination>li>a,
.pagination>li>span {
position: relative;
float: left;
padding: 6px 12px;
margin-left: -1px;
line-height: 1.42857143;
color: #337ab7;
text-decoration: none;
background-color: #fff;
border: 1px solid #ddd
}
.pagination>li:first-child>a,
.pagination>li:first-child>span {
margin-left: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px
}
.pagination>li:last-child>a,
.pagination>li:last-child>span {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px
}
.pagination>li>a:focus,
.pagination>li>a:hover,
.pagination>li>span:focus,
.pagination>li>span:hover {
z-index: 3;
color: #23527c;
background-color: #eee;
border-color: #ddd
}
.pagination>.active>a,
.pagination>.active>a:focus,
.pagination>.active>a:hover,
.pagination>.active>span,
.pagination>.active>span:focus,
.pagination>.active>span:hover {
z-index: 2;
color: #fff;
cursor: default;
background-color: #337ab7;
border-color: #337ab7
}
.pagination>.disabled>a,
.pagination>.disabled>a:focus,
.pagination>.disabled>a:hover,
.pagination>.disabled>span,
.pagination>.disabled>span:focus,
.pagination>.disabled>span:hover {
color: #777;
cursor: not-allowed;
background-color: #fff;
border-color: #ddd
}
.pagination-lg>li>a,
.pagination-lg>li>span {
padding: 10px 16px;
font-size: 18px;
line-height: 1.3333333
}
.pagination-lg>li:first-child>a,
.pagination-lg>li:first-child>span {
border-top-left-radius: 6px;
border-bottom-left-radius: 6px
}
.pagination-lg>li:last-child>a,
.pagination-lg>li:last-child>span {
border-top-right-radius: 6px;
border-bottom-right-radius: 6px
}
.pagination-sm>li>a,
.pagination-sm>li>span {
padding: 5px 10px;
font-size: 12px;
line-height: 1.5
}
.pagination-sm>li:first-child>a,
.pagination-sm>li:first-child>span {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px
}
.pagination-sm>li:last-child>a,
.pagination-sm>li:last-child>span {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px
}
.pager {
padding-left: 0;
margin: 20px 0;
text-align: center;
list-style: none
}
.pager li {
display: inline
}
.pager li>a,
.pager li>span {
display: inline-block;
padding: 5px 14px;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 15px
}
.pager li>a:focus,
.pager li>a:hover {
text-decoration: none;
background-color: #eee
}
.pager .next>a,
.pager .next>span {
float: right
}
.pager .previous>a,
.pager .previous>span {
float: left
}
.pager .disabled>a,
.pager .disabled>a:focus,
.pager .disabled>a:hover,
.pager .disabled>span {
color: #777;
cursor: not-allowed;
background-color: #fff
}
</style>
</head>
<body ng-controller="JiraController">
<div class="col-sm-12">
<div class="row" style="background: #09c;">
<div style="margin-left: auto; margin-right: auto;">
<img src="/logo.png" height="80">
<span class="d-none d-sm-inline"
style="color: white; font-size: 4rem; vertical-align: middle; font-family:'Source Code Pro'">Jira</span>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-item nav-link active" id="nav-myticket-tab" data-toggle="tab" href="#nav-myticket"
role="tab" aria-controls="nav-myticket" aria-selected="true" ng-click="getUserTickets()">My
Ticket</a>
</div>
</nav>
<div class="tab-content" id="nav-tabContent">
<div class="tab-pane fade show active" id="nav-myticket" role="tabpanel"
aria-labelledby="nav-myticket-tab">
<div class="col-sm-12" style="margin:10px">
<div id="loading" ng-show="loading">
<img src="spinner.gif">
</div>
<table ng-show="!loading" class="table table-striped table-bordered table-hover tabel-condensed">
<thead>
<tr>
<td>Key</td>
<td>Priority</td>
<td>Summary</td>
<td>Assignee</td>
<td>Status</td>
<td>Due Date</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="data in myticketIssuesData">
<td>
<a href={{data.fields.customfield_10023._links.web}} target="_blank">
{{data.key}}
</a>
</td>
<td>{{data.fields.priority.name}}</td>
<td>{{data.fields.summary}}</td>
<td>{{data.fields.assignee.displayName}}</td>
<td>{{data.fields.status.name}}</td>
<td>{{data.fields.duedate}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td align="center" colspan="6">
<!-- <span class="form-group pull-left page-size form-inline">
<select id="ddlPageSize" class="form-control control-color"
ng-model="pageSizeSelected" ng-change="changePageSize()">
<option value="5">5</option>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
</select>
</span> -->
<div class="pull-right">
<pagination total-items="totalCount" ng-change="pageChanged()"
items-per-page="pageSizeSelected" direction-links="true"
ng-model="pageIndex" max-size="maxSize" class="pagination"
boundary-links="true" rotate="false" num-pages="numPages">
</pagination>
<a style="margin-left: 640px;" class="btn btn-primary">Page: {{pageIndex}} / {{numPages}}</a>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

Resources