How to add 2D array values to ng-repeat - angularjs

I have a 2d array which has data something like this,
categoryinfo[0][0] = {"name": "apple", "category": { "name": "fruits","id": "09a8597d"}}
categoryinfo[0][1] = {"name": "orange", "category": { "name": "fruits","id": "09a8697d"}}
categoryinfo[1][0] = {"name": "fish", "category": { "name": "meat","id": "09a8447d"}}
I want to display these data according to the category, As you can see the [0]the index has all the fruit items and the [1]index has all the meat items.
I want to display these as,
Fruits
Apple
Orange
meat
fish
<table>
<thead>
<tr>
<th>{{categoryinfo[0][0].category.name}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="formnames in categoryinfo">
<td>{{formnames[0].name}}</td>
</tr>
<tr ng-repeat="formnames in categoryinfo">
<td>{{formnames[1].name}}</td>
</tr>
</tbody>
</table>
to be more specific something like this above. But I cant figure out how to do this dynamically without hardcoding like this.

2D arrays are just arrays in an array, just loop over them layer by layer will do.
<table>
<thead ng-repeat-start="category in categoryinfo">
<tr>
<th>{{category[0].category.name}}</th>
</tr>
</thead>
<tbody ng-repeat-end>
<tr ng-repeat="item in category">
<td>{{item.name}}</td>
</tr>
</tbody>
</table>

You repeat them using $index.
The first iteration iterates over y(vertical) and then the one inside gives you x(horizontal) values.
Have a look at the code below.
var app = angular.module('repeatSamples', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.categoryinfo = [];
$scope.categoryinfo[0] = []
$scope.categoryinfo[0][0] = {
"name": "apple",
"category": {
"name": "fruits",
"id": "09a8597d"
}
}
$scope.categoryinfo[0][1] = {
"name": "orange",
"category": {
"name": "fruits",
"id": "09a8697d"
}
}
$scope.categoryinfo[1] = []
$scope.categoryinfo[1][0] = {
"name": "fish",
"category": {
"name": "meat",
"id": "09a8447d"
}
}
$scope.categoryinfo[1][1] = {
"name": "mutton",
"category": {
"name": "meat",
"id": "09a8447d"
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<body ng-app="repeatSamples" ng-controller="MainCtrl">
<table class="table-bordered" ng-repeat="category in categoryinfo">
<thead>
<tr>
<th>{{category[$index].category.name}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="formnames in categoryinfo[$index]">
<td>{{formnames.name}}</td>
</tr>
</tbody>
</table>
</body>

As Commented,
I guess this should do it, though not tried <div ng-repeat="c in category"><h3>{{c[0].category.name}} <p ng-repeat="list in c">{{list.name}}</h3>
Idea:
Since you have 2-D array, you will have to use 2 loops. One to iterate over parent list and other to loop over child list.
Also since you have already grouped items based on category, you can access first element for title.
If the data structure is not fixed and you can change it, you can look into creating a hashmap. You would still need 2 loops but that might make it easier to retrieve data.
function MainCtrl($scope) {
$scope.categoryInfo = {
fruits: [
{"name": "apple","id": "09a8597d"},
{"name": "orange", "id": "09a8697d"}
],
meat: [
{"name": "fish", "id": "09a8447d"}
]
}
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<body ng-app ng-controller="MainCtrl">
<div ng-repeat="(key, value) in categoryInfo">
<h3>{{key}} </h3>
<p ng-repeat="list in value">{{list.name}}</p>
</div>
</body>
Sample code:
function MainCtrl($scope) {
var categoryInfo = [[],[]]
categoryInfo[0][0] = {"name": "apple", "category": { "name": "fruits","id": "09a8597d"}}
categoryInfo[0][1] = {"name": "orange", "category": { "name": "fruits","id": "09a8697d"}}
categoryInfo[1][0] = {"name": "fish", "category": { "name": "meat","id": "09a8447d"}}
$scope.categoryInfo = categoryInfo;
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<body ng-app ng-controller="MainCtrl">
<div ng-repeat="c in categoryInfo">
<h3>{{c[0].category.name}} </h3>
<p ng-repeat="list in c">{{list.name}}</p>
</div>
</body>

Related

Angular JS orderBy is not working with Dates

orderBy feature is not working with the dates when i try to use in the ng-repeat
Here I wanted to sort the entried based on the executedOn
I wanted to sort element the latest date should be reflected at the top.
Can someone help me
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.details = [
{
"id": 255463,
"orderId": 226433,
"status": 1,
"executedOn": "25/Sep/17",
"executedBy": "Person A",
"executedByDisplay": "Person A",
"cycleId": 4042,
"cycleName": "Cycle A",
"versionId": 21289,
"versionName": "Version A",
"issueKey": "A"
},
{
"id": 255433,
"orderId": 226403,
"status": 1,
"executedOn": "1/Mar/17",
"executedBy": "Person B",
"executedByDisplay": "Person B",
"cycleId": 4041,
"cycleName": "Cycle B",
"versionId": 21289,
"versionName": "Version A",
"issueKey": "B"
},
{
"id": 255432,
"orderId": 226402,
"status": 1,
"executedOn": "1/Apr/17",
"executedBy": "Person B",
"executedByDisplay": "Person B",
"cycleId": 4041,
"cycleName": "Cycle B",
"versionId": 21289,
"versionName": "Version A",
"issueKey": "C"
}
];
});
th, td {
border-bottom: 1px solid #ddd;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="myApp">
<body ng-controller="MainCtrl">
<table class="table h6">
<thead>
<tr>
<th>#</th>
<th>Cycle Name</th>
<th>Execution Completed</th>
<th>Total Test Cases</th>
</tr>
</thead>
<tr ng-repeat="x in details | orderBy :'executedOn'">
<td>{{$index+1}}</td>
<td>{{x.cycleName}}</td>
<td>{{x.executedOn | date:'d-MMM-yy'}}</td>
<td>{{x.versionName}}</td>
</tr>
</table>
</body>
</html>
What about to convert "executedOn" to Date Object: new Date("25/Sep/17"),
You can do that as:
$scope.details.map(function(item){
item.executedOn = new Date(item.executedOn);
return item;
});
The sorting will work properly
<tr ng-repeat="x in details | orderBy :'executedOn'">
<td>{{$index+1}}</td>
<td>{{x.cycleName}}</td>
<td>{{x.executedOn | date:'d-MMM-yy'}}</td>
<td>{{x.versionName}}</td>
</tr>
Demo Plunker
You can use A getter function as orderBy expression. This function will be called with each item as argument and the return value will be used for sorting. see details in demo
js
$scope.makerightorder = function(x){
return new Date(x.executedOn);
}
obviously use true as 2nd argument to see latest first
html
<tr ng-repeat="x in details | orderBy :makerightorder:true ">
<td>{{$index+1}}</td>
<td>{{x.cycleName}}</td>
<td>{{x.executedOn | date:'d-MMM-yy'}}</td>
<td>{{x.versionName}}</td>
</tr>

Filter unique value per key in angularjs and get checked

I have an angular object, i have to show its records with filter and sorting. Also i have to show the records of unique values per keys within the object with checkbox.
I shows record with filter and sorting also i showed the unique values per key with checkbox.
Now i have to get the values of these checkbox per key.
Here is my code with plunker url below.
index.html
<body ng-controller="myController">
<label ng-repeat="option in structure.tabs">
<input type="checkbox" ng-model="option.selected">{{option.index}}
</label>
<table border="1" width="100%">
<tr>
<th ng-repeat="header in structure.tabs" ng-show="header.selected" ng-click="sortData(header.filter)">{{header.index}}</th>
</tr>
<tr ng-repeat="data in structure.info | orderBy:sortColumn:reverseSort">
<td ng-show="structure.tabs[0].selected">{{data.name}}</td>
<td ng-show="structure.tabs[1].selected">{{data.age}}</td>
<td ng-show="structure.tabs[2].selected">{{data.city}}</td>
<td ng-show="structure.tabs[3].selected">{{data.designation}}</td>
</tr>
</table>
<h1>Unique Values Table (per key)</h1>
<table border="1" width="100%" style="margin-top: 50px;">
<tr>
<th ng-repeat="header1 in structure.tabs" ng-show="header1.selected">{{header1.index}}</th>
</tr>
<tr>
<td ng-repeat="(hk, hv) in structure.tabs" ng-show="hv.selected">
<table border='1'>
<tr ng-repeat="(dk, dv) in structure.info | unique:hv.filter">
<td>
<input type="checkbox">{{dv[hv.filter]}}
</td>
</tr>
</table>
<br>
<button ng-click="getChecked(hv.filter)">Get Checked</button>
</td>
</tr>
</table>
</body>
app.js
var app = angular.module('myApp', []);
app.controller("myController", function ($scope,$log) {
$scope.sortColumn="name";
$scope.reverseSort=false;
$scope.sortData=function(column) {
$scope.reverseSort=($scope.sortColumn==column) ? !$scope.reverseSort : false;
$scope.sortColumn=column;
}
$scope.structure={
"tabs": [
{
"index": "Name",
"filter": "name",
"selected": true
},
{
"index": "Age",
"filter": "age",
"selected": true
},
{
"index": "City",
"filter": "city",
"selected": true
},
{
"index": "Designation",
"filter": "designation",
"selected": true
}
],
"info": [
{
"name": "Abar",
"age": "27",
"city": "Ghaziabad",
"designation": "Php Developer"
},
{
"name": "Abar",
"age": "27",
"city": "Okhla",
"designation": "Html Developer"
},
{
"name": "Nishant",
"age": "25",
"city": "Delhi",
"designation": "Angular Developer"
},
{
"name": "Amit",
"age": "30",
"city": "Noida",
"designation": "Android Developer"
}
]
};
$scope.getChecked = function(tab) {
alert("Need to get all checked value of key: "+tab);
}
});
app.filter('unique', function() {
return function (arr, field) {
var o = {}, i, l = arr.length, r = [];
for(i=0; i<l;i+=1) {
o[arr[i][field]] = arr[i];
}
for(i in o) {
r.push(o[i]);
}
return r;
};
});
See in plunker http://embed.plnkr.co/wblXhejmSWApBeCAusaI/
You can do like below example:
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />'); </script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
<script src="script.js"></script>
</head>
<body ng-controller="myController">
<h1>Filter Table</h1>
<label ng-repeat="option in structure.tabs">
<input type="checkbox" ng-model="option.selected">{{option.index}}
</label>
<table border="1" width="100%">
<tr>
<th ng-repeat="header in structure.tabs" ng-show="header.selected" ng-click="sortData(header.filter)">{{header.index}}</th>
</tr>
<tr ng-repeat="data in structure.info | orderBy:sortColumn:reverseSort">
<td ng-show="structure.tabs[0].selected">{{data.name}}</td>
<td ng-show="structure.tabs[1].selected">{{data.age}}</td>
<td ng-show="structure.tabs[2].selected">{{data.city}}</td>
<td ng-show="structure.tabs[3].selected">{{data.designation}}</td>
</tr>
</table>
<h1>Unique Values Table (per key)</h1>
<table border="1" width="100%" style="margin-top: 50px;">
<tr>
<th ng-repeat="header1 in structure.tabs" ng-show="header1.selected">{{header1.index}}</th>
</tr>
<tr>
<td ng-repeat="(hk, hv) in structure.tabs" ng-show="hv.selected">
<table border='1'>
<tr ng-repeat="(dk, dv) in structure.info | unique:hv.filter">
<td>
<input ng-model="item" type="checkbox" ng-change="getCheckedValues(item,dv,hv.filter)">{{dv[hv.filter]}}
</td>
</tr>
</table>
<br>
<button ng-click="getChecked(hv.filter)">Get Checked</button>
</td>
</tr>
</table>
</body>
</html>
app.js
var app = angular.module('myApp', []);
app.controller("myController", function ($scope,$log) {
$scope.sortColumn="name";
$scope.reverseSort=false;
$scope.sortData=function(column) {
$scope.reverseSort=($scope.sortColumn==column) ? !$scope.reverseSort : false;
$scope.sortColumn=column;
}
var array = []
array["name"] = [];
array["age"] = [];
array["designation"] = [];
array["city"] = [];
$scope.getCheckedValues = function(e,val,key){
console.log(val)
if(e){
array[key].push(e)
}else{
array[key].shift()
}
}
$scope.structure={
"tabs": [
{
"index": "Name",
"filter": "name",
"selected": true
},
{
"index": "Age",
"filter": "age",
"selected": true
},
{
"index": "City",
"filter": "city",
"selected": true
},
{
"index": "Designation",
"filter": "designation",
"selected": true
}
],
"info": [
{
"name": "Abar",
"age": "27",
"city": "Ghaziabad",
"designation": "Php Developer"
},
{
"name": "Abar",
"age": "27",
"city": "Okhla",
"designation": "Html Developer"
},
{
"name": "Nishant",
"age": "25",
"city": "Delhi",
"designation": "Angular Developer"
},
{
"name": "Amit",
"age": "30",
"city": "Noida",
"designation": "Android Developer"
}
]
};
$scope.getChecked = function(tab) {
alert("Need to get all checked value of key: "+tab);
console.log(array[tab])
}
});
app.filter('unique', function() {
return function (arr, field) {
var o = {}, i, l = arr.length, r = [];
for(i=0; i<l;i+=1) {
o[arr[i][field]] = arr[i];
}
for(i in o) {
r.push(o[i]);
}
return r;
};
});
Alright. Apologies for my previous answer I completely botched the question.
Anyhow I spent almost an hour trying to solve this and managed to do it using $scope.$$watchers[0].last and underscorejs.
//this is how getChecked looks like now
$scope.getChecked = function(tab) {
var selectedKey = tab.$$watchers[0].last;
_.each($scope.structure.info,function(row){
_(row).pairs().filter(function(item){
_.each(item,function(key){
if(key===selectedKey)
{
console.log(row);
return;
}
})
})
})
Above method is responsible for identifying the key and spitting in console, each time you select a key in below table. So check console.
The solution is on below plunkr.
https://embed.plnkr.co/kbiCwhW0RrdHtO3hVEEk/

Angularjs: how to replace , with line break<br> in angular filter

My doubt is simple. How to replace , with line break in angular filter. i also added the demo jsfFiddle
angular
.module('myApp', [])
.filter('nicelist', function() {
return function(input) {
if (input instanceof Array) {
return input.join(",");
}
return input;
}
})
.controller('ctrl', function($scope) {
$scope.todolists = [{
"id": "id_584",
"customer_id": 2,
"url": "url",
"bill_number": "123",
"location": "from_location"
}, {
"id": "id_122",
"customer_id": 3,
"url": "url",
"bill_number": "123",
"location": "from_location"
}, {
"id": "id_128",
"customer_id": 4,
"url": "url",
"bill_number": "123",
"location": "from_location"
}, {
"id": "id_805",
"customer_id": 5,
"url": "url",
"bill_number": "123",
"location": "from_location"
}, {
"id": "id_588",
"customer_id": 6,
"url": "url",
"bill_number": "123",
"location": "from_location"
}, {
"id": ["id_115"," id_114"],
"customer_id": 7,
"url": "url",
"bill_number": "123",
"location": "from_location"
}]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="ctrl">
<table class="table table-hover tr-table transactions" style="width: 100%;">
<thead>
<tr class="search-row pending-orders table-header-row-height tr-table-head">
<th>ID</th>
<th>Bill Number</th>
<th>Location</th>
<th>Url</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="todolist in todolists">
<td>{{todolist.id | nicelist }}</td>
<td>{{todolist.bill_number}}</td>
<td>{{todolist.location}}</td>
<td><a target="_blank" href="{{ 'http://' + todolist.url}}">Download Invoice : <i title="Download Invoice" style="padding-left:5px;cursor:pointer;color:black;" class="fa fa-download"></i></a> </td>
</tr>
</tbody>
</table>
</body>
demo
In the above link, there will be table. In ID column last row contain 2 values which is present in array inside the json. Now instead of comma(,) is there any possible way for line break.
Please share your knowledge.
you use ng-bind-html with injecting sanitize at module level .
html:
<tbody>
<tr ng-repeat="todolist in todolists">
<td ng-bind-html="todolist.id | nicelist"></td>
<td>{{todolist.bill_number}}</td>
<td>{{todolist.location}}</td>
<td><a target="_blank" href="{{ 'http://' + todolist.url}}">Download Invoice : <i title="Download Invoice" style="padding-left:5px;cursor:pointer;color:black;" class="fa fa-download"></i></a> </td>
</tr>
</tbody>
code:
angular.module('myApp', ['ngSanitize']) //Inject here
.filter('nicelist', function() {
return function(input) {
if (input instanceof Array) {
return input.join("<br>");
}
return input;
}
})
working sample up for grabs here.
ng-bind-html directive Documentation
PS: make sure you inject sanitize or you can use different techiques .

A simple mistake in ngInfiniteScroll

I have used ngInfiniteScroll but i have a small problem, i have a set of data in a variable items for eg) 20 but i want to show 5 on first view and the remaining on sliding. but my code loads all the 20 at the first view how can i achieve this, i have given my code below
and my data structure
{
"data": [ {
"name": "Hoarding Majestic",
"code": 456,
"image": "assets/images/images/hoarding1.jpg",
"location": "Majestic"
},
{
"name": "BusShelter ForumMall",
"code": 452,
"image": "assets/images/images/hoarding2.jpg",
"location": "Whitefield"
},
{
"name": "Digital Vijayanagar",
"code": 458,
"image": "assets/images/images/hoarding3.jpg",
"location": "Vijayanagar"
},
{
"name": "Digital Vijayanagar",
"code": 458,
"image": "assets/images/images/hoarding3.jpg",
"location": "Vijayanagar"
}
]
}
html:-
<div layout="row" layout-align="space-around" layout-padding infinite-scroll='loadMore()' infinite-scroll-distance='2'
infinite-scroll-disabled='{{busyLoadingData}}' infinite-scroll-container = "'#content'">
<table class="simple">
<thead>
<tr>
<th class="secondary-text">
<div class="table-header">
<span class="column-title">Asset</span>
</div>
</th>
<th class="secondary-text">
<div class="table-header">
<span class="column-title">Location</span>
</div>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="assets in items">
<!--| priceRange:slider:lower:upper-->
<td>{{assets.name}}</td>
<td>{{ assets.location }}</td>
</tr>
</tbody>
</table>
</div>
and my controller:-
$scope.data = booking.data;
$scope.busyLoadingData = false;
$scope.items = [];
$scope.loadMore = function() {
//console.log("asdfasdfasd");
if($scope.busyLoadingData)
return;
$scope.busyLoadingData = true;
var last = $scope.data[$scope.data.length - 1];
for(var i = 0 ; i <= 5; i++) {
$scope.items.push($scope.data[i]);
//console.log(last);
}
$timeout(function(){$scope.busyLoadingData = false; }, 3000 );
};
Like any infinite scrolling element should do, ng-infinite-scroll is loading more data, than it can display at once. This is to prevent having to less data and having the user reach the bottom even if there is some data left. You can clearly see the effect in this demo. It will start loading data, even if there is still some space left to the bottom of the page.

Binding new Array in a Table using JSonfile

I would like to ask how will you show the "totals array" below the table Event AccountShop, Place and Activity? This code is working but I do have trouble inserting the "total" value in the Json" below the table.
table.html
<!DOCTYPE html>
<html ng-app="myTable">
<head>
<title></title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.0/angular.min.js"></script>
<script type="text/javascript">
var myTable=angular.module('myTable',[]);
myTable.controller('tableCtrl',function($scope,$http){
$http.get("Table.json").success(function(response){
$scope.members=response.events;
});
});
</script>
</head>
<body ng-controller="tableCtrl">
<table border="5">
<tr>
<th>Event</th>
<th>Account Shop</th>
<th>Place</th>
<th>Activity</th>
</tr>
<tr ng-repeat="member in members">
<td>{{member.Event.id}}<br>
{{member.Event.account_id}}<br>
{{member.Event.shop_id}}<br>
<td>
{{member.AccountShop.id}}<br>
{{member.AccountShop.name}}<br>
{{member.AccountShop.short_code}}<br>
</td>
<div ng-repeat="Place in member.Place">
{{Place.id}}<br>
{{Place.name}}<br>
{{Place.lk_country_code}}<br>
</div>
</td>
<td>
<div ng-repeat="Activity in member.Activity">
{{Activity.id}}<br>
{{Activity.short_description}}
</div>
</td>
</tr>
<th>Total</th>
<td>
<div ng-repeat="total members.totals">
{{totals.totals.page}}
{{totals.current}}
{{totals.count}}
{{totals.prevPage}}
{{totals.nextPage}}
{{totals.pageCount}}
{{totals.order}}
{{totals.limit}}
{{totals.options}}
{{totals.paramType}}
</table>
</body>
</html>
Table.json
{
"events": [
{
"Event": {
"id": "59",
"account_id": "1",
"shop_id": "1",
},
"AccountShop": {
"id": "1",
"name": "Gill Divers Pte Ltd",
"short_code": "GILL"
},
"Place": [
{
"id": "537",
"name": "Pulau Dayang",
"lk_country_code": "MY"
}
],
"Activity": [
{
"id": "4011",
"short_description": "sample\r\n"
},
{
"id": "106",
"short_description": "sample\r\n \r\n"
},
{
"id": "1027",
"short_description": "sample\r\n"
}
]
}
],
"totals": [],
"paging": {
"page": 1,
"current": 50,
"count": 3621,
"prevPage": false,
"nextPage": true,
"pageCount": 73,
"order": [],
"limit": 50,
"options": [],
"paramType": "querystring"
}
}
You are missing the in in your ng-repeat. Try:
<div ng-repeat="total in members.totals">
And your totals array is empty:
"totals": []
But I think your real problem is that your trying to access the wrong property and the right property isn't even available on $scope.members
myTable.controller('tableCtrl', function($scope, $http) {
$http.get("Table.json").success(function(response) {
debugger
$scope.members = response.events;
// you need the paging property which isn't in the events array
$scope.totals = response.paging;
});
});

Resources