How to use angular ng-repeat for following JSON object? - javascript

I want to match headfield values with datafield, and have to fetch corresponding value into table data.
HTML:
<table>
<thead>
<tr>
<th ng-repeat="ReportsHead in ReportsHeadList">
{{ReportsHead.headerfield = ReportsHead.headfield}}
</th>
</tr>
</thead>
<tbody>
<tr>
<td ng-repeat="ReportsData in ReportsDataList"
ng-if="ReportsHead.headerfield == ReportsData.datafield">
{{ReportsData.value}}
</td>
</tr>
</tbody>
</table>
JSON Data :
$scope.ReportsHeadList = [
{
'headfield':'Contact Name'
},
{
'headfield':'Phone'
},
{
'headfield':'Email'
}
];
$scope.ReportsDataList = {
[
{
'datafield':'Contact Name',
'value':'Gunaseelan'
},
{
'datafield':'Phone',
'value':'8122911043'
},
{
'datafield':'Email',
'value':'G#gmail.com'
}
],
[
{
'datafield':'Contact Name',
'value':'Gunaseelan'
},
{
'datafield':'Phone',
'value':'8122911043'
},
{
'datafield':'Email',
'value':'G#gmail.com'
}
]
};
Thanks in advance.

First you should parse your Json with JSON.parse(json), and assigment the result to variable. e.g:
$scope.json = JSON.parse(json).
After, you can check for match headfield and data fields with for loop or map, e.g:
for(i in headfield) {
if (i === something)
return i
}
Hope the answar will help, if not leave a comment,
Good luck!

Related

How to reload DataTables with ajax call on thymeleaf?

This is my html where I show the DataTable:
<tr>
<th>ID</th>
<th>Assurance</th>
<th>Credit Balance</th>
<th>Credit Result</th>
<th>Created Date</th>
<th style="text-align: center">Actions</th>
</tr>
</thead>
<tbody>
<tr th:each="credit: ${credits}">
<td th:text="${credit.id}"/>
<td th:text="${credit.assurance}"/>
<td th:text="${credit.creditBalance}"/>
<td th:text="${credit.creditResult}"/>
<td type="date" pattern="yyyy-MM-dd" th:text="${credit.creationDate}"/>
This is the endpoint:
#PreAuthorize("hasRole('ROLE_ADMIN')")
#GetMapping("/showList")
public ModelAndView showCreditList(){
ModelAndView mav = new ModelAndView("list-credits");
mav.addObject("credits",creditService.getAllCredits());
return mav;
}
And this is the script where I create the DataTable:
<script>
$(document).ready(function (){
$("#credit").DataTable();
})
</script>
I have no problem while creating this DataTable. But I tried so many ways like
$(document).ready(function() {
var table = $('#example').DataTable({
"ajax": "/api/data"
});
setInterval( function () {
table.ajax.reload();
}, 5000 );
});
Another try:
$(document).ready(function() {
var table = $('#example').DataTable({
columns: [
{ title: "Field 1" },
{ title: "Field 2" },
{ title: "Field 3" }
],
ajax: {
url: "/api/data",
dataSrc: function(data) {
var tableData = data.map(function(record) {
return [record.field1, record.field2, record.field3];
});
return tableData;
}
}
});
setInterval( function () {
table.ajax.reload();
}, 5000 );
});
But the problem is I am returning a List<Credit> from my endpoint. So ajax.reload simply can't format the data for DataTable. I am using this call from ajax.
#GetMapping("/all")
public List<Credit> getAllCredits(){
return creditService.getAllCredits();
}
Do you have any solution to this? How do I solve it?

Get DataTables data from both local and REST sourced data

I want to use the jquery pluging datatables and complement local data through an external REST ressource.
My table has to columns, Id and RestCalledValue:
<table id="table">
<thead>
<tr>
<th>Id</th>
<th>RestCalledValue</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
My js has an object data, which holds my local data:
let data = [
{
"id": 1
},
{
"id": 2
}
]
My datatables initialisation looks like below: i want to give the second column the returned value from the function getRestDataForId (id).
$(function () {
var table = $('#table').DataTable({
data: data,
columns: [
{
data: "id"
},
{
data: function (row, type, set, meta) {
getRestDataForId(row.id);
},
defaultContent: "-"
}
]
});
});
function getRestDataForId(id) {
fetch('https://jsonplaceholder.typicode.com/todos/' + id)
.then(response => response.json())
.then(data => data.title)
}
I constructed a fiddle here:
https://jsfiddle.net/mxhdwfz6/2/
I must be treating the promise wrong. Looking forward for your input!

Datatable make cell clickable with href included in json itself

I am using bootstrap datatable to make a simple presentation of my json. I am using this json to feed datatable :
{
"manualList":[
{
"number":"WFC2062/05",
"umtype":"PT,SI",
"lang":"DE",
"cdnlink":"http://medias.bsh-partner.com/Documents/5550009686_A.pdf",
"version":"A",
"filelenght":1002357,
"urlstatus":true
},
{
"number":"WFC2062/05",
"umtype":"II,IU",
"lang":"DE",
"cdnlink":"http://medias.bsh-partner.com/Documents/5550009685_B.pdf",
"version":"B",
"filelenght":6377032,
"urlstatus":true
},
{
"number":"WFC2062/06",
"umtype":"PT,SI",
"lang":"DE",
"cdnlink":"http://medias.bsh-partner.com/Documents/5550009686_A.pdf",
"version":"A",
"filelenght":1002357,
"urlstatus":true
},
{
"number":"WFC2062/06",
"umtype":"II,IU",
"lang":"DE",
"cdnlink":"http://medias.bsh-partner.com/Documents/5550009685_B.pdf",
"version":"B",
"filelenght":6377032,
"urlstatus":true
},
{
"number":"WFC2062/07",
"umtype":"II,IU",
"lang":"DE",
"cdnlink":"http://medias.bsh-partner.com/Documents/9000029228_C.pdf",
"version":"C",
"filelenght":5918430,
"urlstatus":true
},
{
"number":"WFC2062/08",
"umtype":"II,IU",
"lang":"DE",
"cdnlink":"http://medias.bsh-partner.com/Documents/9000029228_C.pdf",
"version":"C",
"filelenght":5918430,
"urlstatus":true
}
],
"servicetype":"vibki",
"errormessage":null,
"warning":null
}
Data is in json format and i want to show hyperlink with column number, so my aim to add a column with the text of one manualList number and hyperlink of manuaList's cdnlink. But i don't know how to refer both of them inside one column.
Here is my script that creates datatable :
$(document).ready(function() {
var link = localStorage.getItem("link_url");
var table = $('#example').DataTable( {
"ajax": {
"url": link,
"dataSrc": "manualList"
},
"columns": [
{
"data": "cdnlink",
"render" : function(data, type, row, meta){
if(type === 'display'){
return $('<a>')
.attr('href', data)
.text()
.wrap('<div></div>')
.parent()
.html();
} else {
return data;
}
}
},
{ "data": "lang" }
]
});
$('#example')
.removeClass( 'display' )
.addClass('table table-striped table-bordered');
} );
link_url is giving ajax response that i've mentioned above, so you can this example json to evaluate the response.
Here is simple HTML that includes datatable as example :
<div class="container">
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Number</th>
<th>Language</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Number</th>
<th>Language</th>
</tr>
</tfoot>
</table></div>
I hope someone can help me, many thanks in advance for your responses!
I've checked below link to make column rendering on datatable :
https://datatables.net/examples/advanced_init/column_render.html
So, i've created one more invisible column to put cdnlink there and changed from columns to columnDefs such as :
$(document).ready(function() {
var link = localStorage.getItem("link_url");
var table = $('#example').DataTable( {
"ajax": {
"url": link,
"dataSrc": "manualList"
},
"columnDefs": [
{
"data" : "cdnlink",
"targets" : 2
}
,
{// The `data` parameter refers to the data for the cell (defined by the
// `data` option, which defaults to the column being worked with, in
// this case `data: 0`.
"data" : "number",
"render": function ( data, type, row ) {
return $('<a>')
.attr({target: "_blank",href: row.cdnlink})
.text(data)
.wrap('<div></div>')
.parent()
.html();
},
"targets": 0
},
{
"data" : "lang",
"targets" : 1
},
{ "visible": false, "targets": [ 2 ] }
]
});
$('#example')
.removeClass('display')
.addClass('table table-striped table-bordered');
} );
I've also added column in html file :
<div class="container">
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Number</th>
<th>Language</th>
<th>Link</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Number</th>
<th>Language</th>
<th>Link</th>
</tr>
</tfoot>
</table></div>
Then it worked like charm.

Iterate through nested objects in Meteor.js and insert results into table

I'm trying to make a RuneScape hiscores checker in Meteor.js. I'm now successfully parsing data from their API and saving it as object (you can see app in action here: http://rs-hiscores.meteor.com/). Here's my server code:
var cheerio = Meteor.npmRequire('cheerio');
var BASE_SKILLS = [
'overall', 'attack', 'defence', 'strength', 'hitpoints', 'ranged',
'prayer', 'magic', 'cooking', 'woodcutting', 'fletching', 'fishing',
'firemaking', 'crafting', 'smithing', 'mining', 'herblore', 'agility',
'thieving', 'slayer', 'farming', 'runecrafting', 'hunter', 'construction'
];
var skills = {
'osrs': BASE_SKILLS,
'rs3': BASE_SKILLS.concat('summoning', 'dungeoneering', 'divination')
};
var urls = {
'osrs': 'http://services.runescape.com/m=hiscore_oldschool/index_lite.ws?player=',
'rs3': 'http://hiscore.runescape.com/index_lite.ws?player='
};
Meteor.methods({
lookup: function(player, game) {
if (!urls.hasOwnProperty(game)) {
game = 'rs3';
}
var url = urls[game].concat(encodeURIComponent(player));
result = Meteor.http.get(url);
$ = cheerio.load(result.content);
body = $.html();
parsed = Meteor.call('parseStats', body, skills[game]);
return parsed;
},
parseStats: function(raw, skillsList) {
var stats = raw.split('\n').slice(0, skillsList.length);
var statsObj = { };
stats.forEach(function(stat, index) {
var chunk = stat.split(',');
statsObj[skillsList[index]] = {
rank: +chunk[0],
level: +chunk[1],
xp: +chunk[2]
};
});
return statsObj;
}
});
In my client code, I'm testing lookup method manually by providing player name inside function as an argument:
Meteor.call('lookup', 'zezima', 'rs3', function(error, result) {
if (error) {
console.error(error);
}
console.log(result);
Session.set("data", result);
});
Template.rawdata.helpers({
getData: function() {
return Session.get("data");
}
});
Result in console:
{
agility: {
level: 99,
rank: 174,
xp: 100234567
},
attack: {
level: 99,
rank: 601,
xp: 127370193
},
construction: {
level: 99,
rank: 119,
xp: 141170001
},
and so on...
}
Obviously, when I call getData inside my template in html and render it, it shows: [object Object]. So I want to somehow iterate through objects and insert them into table, that will look like this one:
<table id="rs-hiscores">
<thead>
<tr>
<th>Skill name</th>
<th>Rank</th>
<th>Level</th>
<th>Xp</th>
</tr>
</thead>
<tbody id="rs-hiscore-data">
<tr>
<td>Agility</td>
<td>99</td>
<td>174</td>
<td>109317063</td>
</tr>
<tr>
<td>Attack</td>
<td>99</td>
<td>601</td>
<td>127370193</td>
</tr>
<tr>
<td>Construction</td>
<td>99</td>
<td>119</td>
<td>141170001</td>
</tr>
...and so on ...
</tbody>
</table>
How can I do that? And also - whould it be possible to sort results in the same order as skills are inside BASE_SKILLS? Thank for help in advance.
Okay so you're going to need the data in a decent array, in the order of BASE_SKILLS, using Underscore to map the skills from your data to a new array, your getData helper should look like this:
var data = Session.get('data');
var array = _.map( BASE_SKILLS, function(skillName){
var skill = data[skillName]
return {
name: skillName,
rank: skill.rank,
level: skill.level,
xp: skill.xp
};
});
return array;
This makes a neat array that looks like this:
[
{
name: "overall",
rank: 99,
level: 174,
xp: 109317063
},
{
name: "attack",
rank: 23,
level: 201,
xp: 256311563
},
...etc
]
Then you'll need to get those values into the html in the way you want.
<table id="rs-hiscores">
<thead>
<tr>
<th>Skill name</th>
<th>Rank</th>
<th>Level</th>
<th>Xp</th>
</tr>
</thead>
<tbody id="rs-hiscore-data">
{{#each getData}}
<tr>
<td>{{name}}</td>
<td>{{rank}}</td>
<td>{{level}}</td>
<td>{{xp}}</td>
</tr>
{{/each}}
</tbody>
</table>
You will have the lowercase keys in your table though, overall instead of "Overall" but to get nice names you can just make a dictionary helper function that swaps the one for the other like so: {{getNiceName name}}.

Adding rows with ng-repeat and nested loop

I'm looking for a way to add rows to a table. My data structure looks like that:
rows = [
{ name : 'row1', subrows : [{ name : 'row1.1' }, { name : 'row1.2' }] },
{ name : 'row2' }
];
I want to create a table which looks like that:
table
row1
row1.1
row1.2
row2
Is that possible with angular js ng-repeat? If not, what would be a "angular" way of doing that?
Edit:
Flatten the array would be a bad solution because if i can iterate over the sub elements i could use different html tags inside the cells, other css classes, etc.
More than one year later but found a workaround, at least for two levels (fathers->sons).
Just repeat tbody's:
<table>
<tbody ng-repeat="row in rows">
<tr>
<th>{{row.name}}</th>
</tr>
<tr ng-repeat="sub in row.subrows">
<td>{{sub.name}}</td>
</tr>
</tbody>
</table>
As far as I know all browsers support multiple tbody elements inside a table.
More than 3 years later, I have been facing the same issue, and before writing down a directive I tried this out, and it worked well for me :
<table>
<tbody>
<tr ng-repeat-start="row in rows">
<td>
{{ row.name }}
</td>
</tr>
<tr ng-repeat-end ng-repeat="subrow in row.subrows">
<td>
{{ subrow.name }}
</td>
</tr>
</tbody>
</table>
You won't be able to do this with ng-repeat. You can do it with a directive, however.
<my-table rows='rows'></my-table>
Fiddle.
myApp.directive('myTable', function () {
return {
restrict: 'E',
link: function (scope, element, attrs) {
var html = '<table>';
angular.forEach(scope[attrs.rows], function (row, index) {
html += '<tr><td>' + row.name + '</td></tr>';
if ('subrows' in row) {
angular.forEach(row.subrows, function (subrow, index) {
html += '<tr><td>' + subrow.name + '</td></tr>';
});
}
});
html += '</table>';
element.replaceWith(html)
}
}
});
I'm a bit surprised that so many are advocating custom directives and creating proxy variables being updated by $watch.
Problems like this are the reason that AngularJS filters were made!
From the docs:
A filter formats the value of an expression for display to the user.
We aren't looking to manipulate the data, just format it for display in a different way. So let's make a filter that takes in our rows array, flattens it, and returns the flattened rows.
.filter('flattenRows', function(){
return function(rows) {
var flatten = [];
angular.forEach(rows, function(row){
subrows = row.subrows;
flatten.push(row);
if(subrows){
angular.forEach(subrows, function(subrow){
flatten.push( angular.extend(subrow, {subrow: true}) );
});
}
});
return flatten;
}
})
Now all we need is to add the filter to ngRepeat:
<table class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th>Rows with filter</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows | flattenRows">
<td>{{row.name}}</td>
</tr>
</tbody>
</table>
You are now free to combine your table with other filters if desired, like a search.
While the multiple tbody approach is handy, and valid, it will mess up any css that relies on the order or index of child rows, such as a "striped" table and also makes the assumption that you haven't styled your tbody in a way that you don't want repeated.
Here's a plunk: http://embed.plnkr.co/otjeQv7z0rifPusneJ0F/preview
Edit:I added a subrow value and used it in the table to show which rows are subrows, as you indicated a concern for being able to do that.
Yes, it's possible:
Controller:
app.controller('AppController',
[
'$scope',
function($scope) {
$scope.rows = [
{ name : 'row1', subrows : [{ name : 'row1.1' }, { name : 'row1.2' }] },
{ name : 'row2' }
];
}
]
);
HTML:
<table>
<tr ng-repeat="row in rows">
<td>
{{row.name}}
<table ng-show="row.subrows">
<tr ng-repeat="subrow in row.subrows">
<td>{{subrow.name}}</td>
</tr>
</table>
</td>
</tr>
</table>
Plunker
In case you don't want sub-tables, flatten the rows (while annotating subrows, to be able to differentiate):
Controller:
function($scope) {
$scope.rows = [
{ name : 'row1', subrows : [{ name : 'row1.1' }, { name : 'row1.2' }] },
{ name : 'row2' }
];
$scope.flatten = [];
var subrows;
$scope.$watch('rows', function(rows){
var flatten = [];
angular.forEach(rows, function(row){
subrows = row.subrows;
delete row.subrows;
flatten.push(row);
if(subrows){
angular.forEach(subrows, function(subrow){
flatten.push( angular.extend(subrow, {subrow: true}) );
});
}
});
$scope.flatten = flatten;
});
}
HTML:
<table>
<tr ng-repeat="row in flatten">
<td>
{{row.name}}
</td>
</tr>
</table>
Plunker
Here is an example. This code prints all names of all the people within the peopeByCity array.
TS:
export class AppComponent {
peopleByCity = [
{
city: 'Miami',
people: [
{
name: 'John', age: 12
}, {
name: 'Angel', age: 22
}
]
}, {
city: 'Sao Paulo',
people: [
{
name: 'Anderson', age: 35
}, {
name: 'Felipe', age: 36
}
]
}
]
}
HTML:
<div *ngFor="let personsByCity of peopleByCity">
<div *ngFor="let person of personsByCity.people">
{{ person.name }}
</div>
</div>

Categories