Parsing JSON with data with varing fields - javascript

I am trying to polulate a html table using the JSON reponse. I have parsed and use angluar ng-repeat to fill the table. But now I noticed that the JSON reponse type may vary based on the type of user.
JSON response:
[{
"id": 133,
"account": {
"accountNumber": "6335050000000111",
"accountType": "TSys",
"address": {
"companyName": "",
"street1": "",
"street2": "",
"street3": "",
"street4": "",
"country": "GB",
"prepayBalance": 110
}
},
"lastModifiedDate": "Apr 09, 2020",
"lastModifiedBy": "uk#gmail.com"
}, {
"id": 132,
"account": {
"accountNumber": "6335052400000034",
"accountType": "PREPAY",
"address": {
"companyName": "",
"street1": "",
"street2": "",
"street3": "",
"street4": "",
"country": "GB",
"prepayBalance": 130
},
"bankAccount": {
"id": 54390,
"bankAccountName": "ABC Coompany",
"bankAccountNumber": "3245",
"sortCode": "12-34-56",
"address": {
"street1": "Fidelity Bank",
"street2": "10 BANK STREET",
"street3": "LONDON",
"street4": "SW1A 2AA",
"country": "GB"
}
}
},
"lastModifiedDate": "Apr 09, 2020",
"lastModifiedBy": "ukcase#mailinator.com"
}]
As you can see in the response some may or may not receive "bankAccount" as response. I only need to select those which has bank account but at the same time count all the records.
Example:
count(data.account.accountType) //somehow implement the count logic
count(data.account.bankAccount)
// Main logic
$scope.getAllDd = data.account.bankAccount; // get only those records with bankaccount in response
Which I can use for:
<tr ng-repeat="ddAccounts in getAllDd">
<td>{{ddAccounts.account.accountType}}</td>

Declare the unfiltered accounts separate from the filtered ones.
const app = angular.module('AccountApp', []);
const hasBankAccount = (account) => account.account.bankAccount != null;
app.filter('objectValues', () => {
return (obj) => Object.values(obj).join(', ');
});
app.controller('AccountController', function($scope, $http) {
$scope.filters = {
search: ''
};
// Filter here initially...
$scope.accounts = getJson();
$scope.filteredData = $scope.accounts.filter(hasBankAccount);
// Filter even more on search...
$scope.doSearch = function() {
let filterField = document.querySelector('#txt-filter');
let filterText = filterField.value.trim().toLowerCase();
$scope.filteredData = filterText.length === 0
? $scope.accounts.filter(hasBankAccount)
: $scope.filteredData = $scope.accounts
.filter(hasBankAccount)
.filter(account => {
return account.account.accountNumber.toLowerCase().includes(filterText);
});
};
});
function getJson() {
return [{
"id": 133,
"account": {
"accountNumber": "6335050000000111",
"accountType": "TSys",
"address": {
"companyName": "",
"street1": "",
"street2": "",
"street3": "",
"street4": "",
"country": "GB",
"prepayBalance": 110
}
},
"lastModifiedDate": "Apr 09, 2020",
"lastModifiedBy": "uk#gmail.com"
}, {
"id": 132,
"account": {
"accountNumber": "6335052400000034",
"accountType": "PREPAY",
"address": {
"companyName": "",
"street1": "",
"street2": "",
"street3": "",
"street4": "",
"country": "GB",
"prepayBalance": 130
},
"bankAccount": {
"id": 54390,
"bankAccountName": "ABC Company",
"bankAccountNumber": "3245",
"sortCode": "12-34-56",
"address": {
"street1": "Fidelity Bank",
"street2": "10 BANK STREET",
"street3": "LONDON",
"street4": "SW1A 2AA",
"country": "GB"
}
}
},
"lastModifiedDate": "Apr 09, 2020",
"lastModifiedBy": "ukcase#mailinator.com"
}];
}
table, th, td {
border: 1px solid grey;
border-collapse: collapse;
padding: 0.25em;
font-size: 0.9em;
}
table {
width: 100%;
}
.toolbar {
margin-bottom: 1em;
}
.details {
margin-top: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="AccountApp">
<div ng-controller="AccountController">
<div class="toolbar">
<input type="button" value="Filter" ng-model="query" ng-model-options="{ debounce: 200 }" ng-click="doSearch()">
<input type="text" id="txt-filter">
</div>
<table>
<thead>
<tr>
<th>#</th>
<th>Acct. No.</th>
<th>Acct. Type</th>
<th>Address</th>
<th>Bank Name</th>
<th>Bank Acct. No.</th>
<th>Bank Address</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="account in filteredData | orderBy : 'account.accountNumber' | filter : filters.search">
<td>{{ $index + 1 }}</td>
<td>{{ account.account.accountNumber }}</td>
<td>{{ account.account.accountType }}</td>
<td>{{ account.account.address.country }}</td>
<td>{{ account.account.bankAccount.bankAccountName }}</td>
<td>{{ account.account.bankAccount.bankAccountNumber }}</td>
<td>{{ account.account.bankAccount.address | objectValues }}</td>
</tr>
</tbody>
</table>
<div class="details">
<strong>No. of Accounts: </strong>
<span ng-bind="filteredData.length"></span> /
<span ng-bind="accounts.length"></span>
</div>
</div>
</div>

have you tried with .filter() methods ? ... something like:
$scope.getAllDd = data.account.filter(xx=> xx. bankAccount)
this.totalRecords = data.account.length;
and then
<tr ng-repeat="ddAccounts in getAllDd">
<td>{{ddAccounts.account.accountType}}</td>
Hope it helps you!!

Related

v-for seems to change the array order

Data Object:
{
"headers": {
"location": "Location",
"postcode": "Postcode",
"contributors": "Contributors",
"contributions": "Contributions",
"percentage": "Percentage"
},
"rows": [
{
"postcode": "3018",
"contributors": 2,
"contributions": 2,
"location": "Seaholme",
"percentage": 67
},
{
"postcode": "3013",
"contributors": 1,
"contributions": 1,
"location": "Yarraville West",
"percentage": 33
}
]
}
Template:
<thead>
<tr>
<th v-for="(v, k) in data.result.headers" :key="k">
{{ v }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, i) in data.result.rows" :key="i">
<td :key="j" v-for="(col, j) in row">
{{ col }}
</td>
</tr>
</tbody>
Output:
So the table header and body are two separate objects. While the header seems to follow the order but the row objects don't. How can I make sure they always align correctly?
You can create a computed property of the rows. This would be the same list but with the keys ordered in the order of the header keys. Here is a possible solution:
new Vue({
el: "#app",
data: () => ({
"headers": { "location": "Location", "postcode": "Postcode", "contributors": "Contributors", "contributions": "Contributions", "percentage": "Percentage" },
"rows": [
{ "postcode": "3018", "contributors": 2, "contributions": 2, "location": "Seaholme", "percentage": 67 },
{ "postcode": "3013", "contributors": 1, "contributions": 1, "location": "Yarraville West", "percentage": 33 }
]
}),
computed: {
orderedRows() {
const headers = Object.keys(this.headers);
return this.rows.map(row =>
headers.reduce((orderedRow, key) =>
({ ...orderedRow, [key]: row[key] })
, {})
);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<thead>
<tr>
<th v-for="(v, k) in headers" :key="k">{{ v }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, i) in orderedRows" :key="i">
<td v-for="(col, j) in row" :key="j">{{ col }}</td>
</tr>
</tbody>
</table>
</div>
Another possible way inspired from #CertainPerformance comment:
new Vue({
el: "#app",
data: () => ({
"headers": { "location": "Location", "postcode": "Postcode", "contributors": "Contributors", "contributions": "Contributions", "percentage": "Percentage" },
"rows": [
{ "postcode": "3018", "contributors": 2, "contributions": 2, "location": "Seaholme", "percentage": 67 },
{ "postcode": "3013", "contributors": 1, "contributions": 1, "location": "Yarraville West", "percentage": 33 }
]
}),
computed: {
headerKeys() {
return Object.keys(this.headers);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<thead>
<tr>
<th v-for="(v, k) in headers" :key="k">{{ v }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, i) in rows" :key="i">
<td v-for="(header, j) in headerKeys" :key="j">{{ row[header] }}</td>
</tr>
</tbody>
</table>
</div>

How to print table rows with table rows children in Angular?

I am looking for a way to print data received from API in a table working with Angular. The table have different collapses. The collapses have several rows which at the same time these rows have children rows and some of them have more children rows.
this is the json file:
{
"collapse1": [
{
"name": "Soil",
"budget": 12345,
"child": [
{
"name": "Shopping",
"budget": 12345
},
{
"name": "Financial",
"budget": 12345
}
]
},
{
"name": "Exterior",
"budget": 12345,
"child": [
{
"name": "Shopping",
"budget": 12345
},
{
"name": "Financial",
"budget": 12345
}
]
},
{
"name": "Obra",
"budget": 12345,
"child": [
{
"name": "Shopping",
"budget": 12345
},
{
"name": "Financial",
"budget": 12345
}
]
},
{
"name": "Professional honoraries",
"budget": 12345,
"child": [
{
"name": "Shopping",
"budget": 12345
},
{
"name": "Financial",
"budget": 12345
}
]
}
],
"collapse2":[
{
"name": "Soil",
"budget": 12345,
"child": [
{
"name": "Shopping",
"budget": 12345
},
{
"name": "Financial",
"budget": 12345
}
]
},
{
"name": "Construction",
"budget": 12345,
"child": [
{
"name": "Data Center",
"budget": 12345,
"child": [
{
"name": "Development & Design",
"budget": 12345,
"child": [
{
"name": "Raw Land",
"budget": 12345
},
{
"name": "Land Development",
"budget": 12345
},
{
"name": "Fiber Connection Upgrade",
"budget": 12345
}
]
}
]
}
]
}
]
}
I'm looking for a solution to dynamically print a table with data like in the json file. I tried to do the following just for the first collapse, but it did not work.
<ng-container *ngFor="let collapse of collapse1">
<tr class="group2 collapse" [collapse]="isCollapsedGroup2">
<td>{{ collapse.name }}</td>
<td></td>
<td></td>
</tr>
<ng-container *ngFor="let child of collapse1.child">
<tr class="tablerow-sub collapse" [collapse]="isCollapsedGroup2">
<td>
<em class="pl-3">{{ child.name }}</em>
</td>
<td></td>
<td></td>
</tr>
</ng-container>
</ng-container>
You can use ng-template to have a recursive loop in the template like this
https://stackblitz.com/edit/angular-playground-excmau?file=app%2Fapp.component.html
<ng-template #row let-data="collapse">
<tr>
<td>{{ data.name }}</td>
<td>{{ data.budget }}</td>
</tr>
<ng-container *ngIf="data.child">
<ng-container *ngFor="let child of data.child" [ngTemplateOutlet]="row"
[ngTemplateOutletContext]="{ collapse: child }"></ng-container>
</ng-container>
</ng-template>
<table>
<ng-container *ngFor="let c of collapse">
<ng-container [ngTemplateOutlet]="row" [ngTemplateOutletContext]="{ collapse: c }"></ng-container>
</ng-container>
</table>

Export HTML data to excel

On my UI where I have A HTML table and some Input fields, all the fields have some data including table so what I am trying to do is :-
I want to export HTML full page data into excel,all input fields as well as table data, earlier I was using table2excel plugin but it is only exporting the HTML table data not input fields data
Code
var tableValue = [{
"Name": "vivek",
"Class": "12",
"English": 89,
"Maths": 45,
"Physics": 63
},
{
"Name": "Raul",
"Class": "11",
"English": 55,
"Maths": 45,
"Physics": 23
},
{
"Name": "Sam",
"Class": "12",
"English": 55,
"Maths": 68,
"Physics": 56
},
{
"Name": "Arun",
"Class": "12",
"English": 45,
"Maths": 78,
"Physics": 58
},
{
"Name": "Patric",
"Class": "12",
"English": 86,
"Maths": 45,
"Physics": 62
},
]
function addTable(tableValue) {
var $tbl = $("<table />", {
"class": "table table-striped table-bordered table-hover"
}),
$thd = $("<thead/>"),
$tb = $("<tbody/>"),
$trh = $("<tr/>", {
"class": "text-center"
});
$.each(Object.keys(tableValue[0]), function(_, val) {
$("<th/>").html(val).appendTo($trh);
});
$trh.appendTo($thd);
$.each(tableValue, function(_, item) {
$tr = $("<tr/>");
$.each(item, function(key, value) {
if (typeof(value) === 'number') {
$("<td/>", {
"class": "text-right"
}).html(value).appendTo($tr);
} else {
$("<td/>", {
"class": "text-left"
}).html(value).appendTo($tr);
}
$tr.appendTo($tb);
});
});
$tbl.append($thd).append($tb);
$("#grnReportTable").html($tbl);
}
$("#supplierAddReport").val("STILL FLOOR, NO. 34, 2ND CROSS, SWASTHI ROAD, SHANTINAGAR, BANGALORE, 560027 Contact Name: SURESH, Contact No. 22745206 GST No. : 29210085111, Email Id: ALPINEPRODUCTS#GMAIL.COM")
addTable(tableValue)
$("#export").click(function() {
$("#grnReportTable").table2excel({
filename: "Data"
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"></script>
<script src="https://cdn.rawgit.com/rainabba/jquery-table2excel/1.1.0/dist/jquery.table2excel.min.js"></script>
<div class="container">
<div class="container" id="grnReportTable"></div>
<div class="form-row">
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-3">
<label for="mrk1">Marks 1</label>
<div class="input-group">
<input type="tel" class="form-control" aria-label="Text input with dropdown button" name="mrk1" id="mrk1" readonly="readonly" tabindex="-1" value="50">
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-3">
<label for="mrk2">Marks 2</label>
<div class="input-group">
<input type="tel" class="form-control" aria-label="Text input with dropdown button" name="mrk2" id="mrk2" readonly="readonly" tabindex="-1" value="50.22">
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-3">
<label for="mrk3">Marks3</label>
<div class="input-group">
<input type="tel" class="form-control" aria-label="Text input with dropdown button" name="mrk3" id="mrk3" readonly="readonly" tabindex="-1" value="43">
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-8">
<label for="supplierAddReport">Suppl. Address</label>
<div class="input-group">
<textarea class="form-control" rows="3" readonly="readonly" name="supplierAddReport" id="supplierAddReport"></textarea>
</div>
</div>
</div>
</div>
<button id="export" class="btn btn-default commonButton">
<i class='fas fa-file-export'></i> Export
</button>
<script
src="https://cdn.rawgit.com/rainabba/jquery-table2excel/1.1.0/dist/jquery.table2excel.min.js"></script>
The table to excel plugin only export HTML table but I want to export Full page Data here i am only showing input fields but in my actual code I have some text areas as well as select option
i want to export it like
Instead of convert html to excel, change your scenario to convert JSON to CSV. Because, you have data and your data is JSON, that can convert to html table or CSV or other types, and solution of JSON to CSV is better than html to excel.
First: Prepare data.That means convert your data to your schema, you wanted export.
var tableValue = [
{ // Row for Marks 1
"Name": "Marks 1",
"Class": "50",
"English": "",
"Maths": "",
"Physics": ""
},
{ // Row for Marks 2
"Name": "Marks 2",
"Class": "55.22",
"English": "",
"Maths": "",
"Physics": ""
},
{ // Row for Marks 3
"Name": "Marks 3",
"Class": "43",
"English": "",
"Maths": "",
"Physics": ""
},
{
"Name": "",
"Class": "",
"English": "",
"Maths": "",
"Physics": ""
},
{
"Name": "Name",
"Class": "Class",
"English": "English",
"Maths": "Maths",
"Physics": "Physics"
},
{
"Name": "vivek",
"Class": "12",
"English": 89,
"Maths": 45,
"Physics": 63
},
{
"Name": "Raul",
"Class": "11",
"English": 55,
"Maths": 45,
"Physics": 23
},
{
"Name": "Sam",
"Class": "12",
"English": 55,
"Maths": 68,
"Physics": 56
},
{
"Name": "Arun",
"Class": "12",
"English": 45,
"Maths": 78,
"Physics": 58
},
{
"Name": "Patric",
"Class": "12",
"English": 86,
"Maths": 45,
"Physics": 62
}
]
, now You do not need any additional library, use this code :
// JAVASCRIPT
function convertToCSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
for (var i = 0; i < array.length; i++) {
var line = '';
for (var index in array[i]) {
if (line != '') line += ','
line += array[i][index];
}
str += line + '\r\n';
}
return str;
}
function exportCSVFile(headers, items, fileTitle) {
if (headers) {
items.unshift(headers);
}
// Convert Object to JSON
var jsonObject = JSON.stringify(items);
var csv = this.convertToCSV(jsonObject);
var exportedFilenmae = fileTitle + '.csv' || 'export.csv';
var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, exportedFilenmae);
} else {
var link = document.createElement("a");
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", exportedFilenmae);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
function download(){
var headers = {
Name: '', // remove commas to avoid errors
Class: '',
English: '',
Maths: '',
Physics: ''
};
itemsNotFormatted = [
{
"Name": "Marks 1",
"Class": "50",
"English": "",
"Maths": "",
"Physics": ""
},
{
"Name": "Marks 2",
"Class": "55.22",
"English": "",
"Maths": "",
"Physics": ""
},
{
"Name": "Marks 3",
"Class": "43",
"English": "",
"Maths": "",
"Physics": ""
},
{
"Name": "",
"Class": "",
"English": "",
"Maths": "",
"Physics": ""
},
{
"Name": "Name",
"Class": "Class",
"English": "English",
"Maths": "Maths",
"Physics": "Physics"
},
{
"Name": "vivek",
"Class": "12",
"English": 89,
"Maths": 45,
"Physics": 63
},
{
"Name": "Raul",
"Class": "11",
"English": 55,
"Maths": 45,
"Physics": 23
},
{
"Name": "Sam",
"Class": "12",
"English": 55,
"Maths": 68,
"Physics": 56
},
{
"Name": "Arun",
"Class": "12",
"English": 45,
"Maths": 78,
"Physics": 58
},
{
"Name": "Patric",
"Class": "12",
"English": 86,
"Maths": 45,
"Physics": 62
}
];
var itemsFormatted = [];
// format the data
itemsNotFormatted.forEach((item) => {
itemsFormatted.push({
Name: item.Name, // remove commas to avoid errors,
Class: item.Class,
English: item.English,
Maths: item.Maths,
Physics: item.Physics
});
});
var fileTitle = 'SCORES'; // or 'my-unique-title'
exportCSVFile(headers, itemsFormatted, fileTitle); // call the exportCSVFile() function to process the JSON and trigger the download
}
// HTML CODE
<div class="download-wrapper" onClick="download()">
<p><i class="material-icons">file_download</i></p>
<p>Download Demo CSV File</p>
</div>
<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="js,result" data-user="danny_pule" data-slug-hash="WRgqNx" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="JSON to CSV">
<span>See the Pen <a href="https://codepen.io/danny_pule/pen/WRgqNx/">
JSON to CSV</a> by Danny Pule (#danny_pule)
on CodePen.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
// RESULT

Angular JS: How to use ng-repeat for complex objet

I have a complex object coming from the web service as shown below, how to display PatientId and description, if anyone have any good idea, please help me thru it.:
$scope.myData = {"PatientSearchResponse": {
"pageNumber": 1,
"pageSize": 50,
"patDataBean": [
{
"gender": {
"code": "male",
"description": "Male",
"type": "gender"
},
"patDateofBirth": "1997/06/19",
"patFirstName": "aman",
"patLastName": "elvis",
"patSurvivalStat": {
"code": "A",
"description": "Alive",
"type": "patient_status"
},
"patientIdentifier": {
"OID": "589a9cf6-4513-49e1-bd5c-c7363849ed93",
"organizationId": {
"PK": 54,
"siteName": "CTRP"
},
"patientId": "1"
}
},
{
"gender": {
"code": "male",
"description": "Male",
"type": "gender"
},
"patDateofBirth": "2001/07/18",
"patFirstName": "Elvis",
"patLastName": "Harvey",
"patSurvivalStat": {
"code": "dead",
"description": "Dead",
"type": "patient_status"
},
"patientIdentifier": {
"OID": "151d0222-3726-40ee-8f69-0a6800727607",
"organizationId": {
"OID": "83d09227-9c65-4d7b-94da-baaf5c07b38a",
"siteName": "Texas"
},
"patientId": "100"
}
}]}}
In my HTML I am using ng-repeat as:
<td ng-repeat="(key, value) in grid.columns">
<div>
<p >{{row[key]}}</p>
</div>
</td>
my JS file as:
myDataContainer = $scope.myData.PatientSearchResponse.patDataBean;
$scope.grid.columns = {patientIdentifier: "Patient Id",patFirstName: "First Name",patLastName: "Last Name",patDateofBirth: "Date of Birth",patSurvivalStat: "Description"};
angular.forEach(myDataContainer, function (values, index) {
$scope.grid.rows.push(values);
});
Why you can just do this :
<td ng-repeat="pat in myData.PatientSearchResponse.patDataBean">
{{pat.patientIdentifier}} - {{pat.patSurvivalStat.description}}
</td>
Try this man:
angular.module('app', [])
.controller('Controller', ['$scope', function($scope) {
$scope.myData = {"PatientSearchResponse": {
"pageNumber": 1,
"pageSize": 50,
"patDataBean": [
{
"gender": {
"code": "male",
"description": "Male",
"type": "gender"
},
"patDateofBirth": "1997/06/19",
"patFirstName": "aman",
"patLastName": "elvis",
"patSurvivalStat": {
"code": "A",
"description": "Alive",
"type": "patient_status"
},
"patientIdentifier": {
"OID": "589a9cf6-4513-49e1-bd5c-c7363849ed93",
"organizationId": {
"PK": 54,
"siteName": "CTRP"
},
"patientId": "1"
}
},
{
"gender": {
"code": "male",
"description": "Male",
"type": "gender"
},
"patDateofBirth": "2001/07/18",
"patFirstName": "Elvis",
"patLastName": "Harvey",
"patSurvivalStat": {
"code": "dead",
"description": "Dead",
"type": "patient_status"
},
"patientIdentifier": {
"OID": "151d0222-3726-40ee-8f69-0a6800727607",
"organizationId": {
"OID": "83d09227-9c65-4d7b-94da-baaf5c07b38a",
"siteName": "Texas"
},
"patientId": "100"
}
}]}}
}]);
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-controller="Controller">
<table>
<tr>
<th>Id</th>
<th>Description</th>
</tr>
<tr ng-repeat="m in myData.PatientSearchResponse.patDataBean">
<td>{{m.patientIdentifier.patientId}}</td>
<td>{{m.patSurvivalStat.description}}</td>
</tr>
</table>
</body>
</html>
Would be more practical to make columns an array of objects with standardized keys
$scope.grid.columns = [
{property : 'patientIdentifier', heading : "Patient Id"},
{property : 'patFirstName', heading : "First Name"},
{property : 'patLastName', heading : "Last Name"},
{property : 'patDateofBirth', heading : "Date of Birth"},
{property : 'patSurvivalStat', heading : "Description"}
]
Then use those to set both headings and content
<table>
<thead>
<tr>
<th ng-repeat="col in grid.columns">{{::col.heading}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in myData.patDataBean">
<td ng-repeat="col in grid.columns">{{::item[col.property]}}</td>
</tr>
</tbody>
</table>

AngularJS - Filter on ng-repeat, hiding the column heading

I have a massive JSON response from a REST service that contains lots of cities over the world... the structure is like this (here's just a sample... it would normally consist of 100-200 places and comes from a service - I have just set it to the $scope item for better understanding):
$scope.cityData = [
{
"country": "Deutschland",
"cities": [
{
"id": 1,
"name": "Berlin",
"country": "Deutschland",
"browserUrl": "berlin",
"clusterId": null
},
{
"id": 2,
"name": "Hamburg",
"country": "Deutschland",
"browserUrl": "hamburg",
"clusterId": null
},
{
"id": 3,
"name": "München",
"country": "Deutschland",
"browserUrl": "muenchen",
"clusterId": null
},
{
"id": 4,
"name": "Köln",
"country": "Deutschland",
"browserUrl": "koeln",
"clusterId": null
}
]
},
{
"country": "Schweiz",
"cities": [
{
"id": 15,
"name": "Zürich",
"country": "Schweiz",
"browserUrl": "zuerich",
"clusterId": null
},
{
"id": 16,
"name": "Geneva",
"country": "Schweiz",
"browserUrl": "geneva",
"clusterId": null
}
]
},
{
"country": "Österreich",
"cities": [
{
"id": 19,
"name": "Vienna",
"country": "Österreich",
"browserUrl": "vienna",
"clusterId": null
},
{
"id": 20,
"name": "Graz",
"country": "Österreich",
"browserUrl": "graz",
"clusterId": null
},
{
"id": 20,
"name": "Linz",
"country": "Österreich",
"browserUrl": "linz",
"clusterId": null
}
]
}
];
Now on my interface I wish to group these like so:
- Country
---- City
---- City
---- City
- Country
---- City
---- City
---- City
I also wish to filter the repeat using an input field, so I have the following input and ng-repeats on my interface:
<input type="text" ng-model="cityFilter">
<div class="row">
<div class="col-xs-12" ng-repeat="c in cityData | filter: c.country">
{{ c.country }}
<div class="col-xs-12" ng-repeat="d in c.cities | filter: cityFilter">
{{ d.name }}
</div>
</div>
</div>
this works great however the c.country title is always shown regardless of the filter... how should I change my HTML / directives so that the c.country disappears when the cityFilter filter contains a city name that is not applicable / found in that country?
Thanks in advance.
Enclose country in a span and Use ng-show.
<input type="text" ng-model="cityFilter">
<div class="row">
<div class="col-xs-12" ng-repeat="c in cityData | filter: c.country">
<span ng-show="(c.cities | filter: cityFilter).length > 0">{{ c.country }}</span>
<div class="col-xs-12" ng-repeat="d in c.cities | filter: cityFilter">
{{ d.name }}
</div>
</div>
</div>

Categories

Resources