I have to build an array like this :
[{'test1': 't1', 'test2' :'t2'},
{'test3' :'t3', 'test4': 't4' },
{'test5': 't5', 'test6' :'t6'},
{'test7' :'t7' , 'test8': 't7' }]
It will be an array of objects.
The object will have always have two key/value pairs.
Key and values will be dynamic.
I have to loop through the object below to build the array:
In the end, I have got to build a table out of the array, which will look like this:
It has to be a 2-columns table, with the key and value.
HTML:
<table class="detailList" >
<tbody>
<tr></tr>
<tr>
<th class="labelCol" scope="row"> <label>test1</label> </th>
<td class="dataCol"> t1</td>
<th class="labelCol" scope="row"> <label>test2</label> </th>
<td class="dataCol"> t2</td>
</tr>
<tr>
<th class="labelCol" scope="row"> <label>test3</label> </th>
<td class="dataCol"> t3</td>
<th class="labelCol" scope="row"> <label>test4</label> </th>
<td class="dataCol"> t4</td>
</tr>
<tr>
<th class="labelCol" scope="row"> <label>test5</label> </th>
<td class="dataCol"> t5</td>
<th class="labelCol" scope="row"> <label>test6</label> </th>
<td class="dataCol"> t6</td>
</tr>
<tr>
<th class="labelCol" scope="row"> <label>test7</label> </th>
<td class="dataCol"> t7</td>
<th class="labelCol" scope="row"> <label>test8</label> </th>
<td class="dataCol"> t7</td>
</tr>
</tbody>
</table>
Any idea how to do this?
Here is how I would create that table:
Working jsFiddle
var testObject = {
some_key: {
key1: '1',
key2: '2',
key3: '3',
}
};
var elements = [];
var last = null;
// loop over the keys in the object in question
$.each(testObject.some_key, function(key, value) {
var item = '<th class="labelCol" scope="row"><label>' + key + '</label></th><td class="dataCol">' + value + '</td>';
if (!last) { // if no last item, set this row to last dont add to the array of elements just yet, we need the other two columns first
last = item;
} else {
// if we already have a last, add these two columns to it, then add it to our array of elements
elements.push(last + item);
last = null;
}
});
if (last) {
// at the end, if we still have a "last" hanging around, add two empty columns
var item = '<th class="labelCol" scope="row"><label></label></th><td class="dataCol"></td>';
elements.push(last + item);
}
// join the array wrapping each set of 4 columns with a tr
var rows = '<tr>' + elements.join('<tr></tr>') + '</tr>';
$('.detailList tbody').html(rows);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="detailList">
<tbody>
</tbody>
</table>
What a crazy requirement. I like it. Here's my take on it. (Didn't test it)
var twoPairArray = []; //array to be returned
var twoPairObj = {}; //temp obj for manipulation
for(var key in targetObj) //target obj has the keys to be processed
{
if(Object.keys(twoPairObj).length == 2) //does temp obj have enough keys?
{
twoPairArray.push(JSON.parse(JSON.stringify(twoPairObj))); //sloppy clone of temp obj
twoPairObj = {}; //reset the temp obj.
}
twoPairObj[key] = targetObj[key]; //temp obj being manipulated into this craziness
}
Related
I have tried few methods but unable to get the desired output.
Here is my table like
<table>
<tr>
<th> Name </th>
<th> Age </th>
</tr>
<tr>
<td> foo </td>
<td> 20 </td>
</tr>
<tr>
<td> Boo </td>
<td> 24 </td>
</tr>
</table>
I want the desired jSON output as follows
[{
Name: 'Foo',
Age: 20
},{
Name: 'Boo',
Age: 24
}]
Can somebody please help?
Hello you can do like this :
const html = `<tr>
<th> Name </th>
<th> Age </th>
</tr>
<tr>
<td> foo </td>
<td> 20 </td>
</tr>
<tr>
<td> Boo </td>
<td> 24 </td>
</tr>`;
// For plug and play sample, i just create dummy table.
const tableEl = document.createElement('table');
tableEl.innerHTML = html;
const output = [];
// Little trick to make querySelectorAll as iterable by foreach.
[].forEach.call(
tableEl.querySelectorAll('tr'),
//Uncomment for TypeScript strong type : (lineElement: HTMLElement) => {
(lineElement) => {
const rows = lineElement.querySelectorAll('td');
if(rows.length >= 2) {
output.push(
{
name : rows[0].innerText,
age : rows[1].innerText,
}
);
}
});
console.log(output);
__ UPDATE 1 : Dynamic attribute detection from th ___
const html = `<tr>
<th> Name </th>
<th> Age </th>
</tr>
<tr>
<td> foo </td>
<td> 20 </td>
</tr>
<tr>
<td> Boo </td>
<td> 24 </td>
</tr>`;
// For plug and play sample, i just create dummy table by programming way
const tableEl = document.createElement('table');
tableEl.innerHTML = html;
const output:any[] = [];
const keys: string[] = [];
// Little trick to make querySelectorAll as iterable by foreach.
[].forEach.call(
tableEl.querySelectorAll('tr'),
(lineElement: HTMLElement) => {
const rows = lineElement.querySelectorAll('td,th');
/**
* If is th tag, we store all items to keys array.
*/
if(rows[0].nodeName === 'TH') {
//We replace remove all whitespace char from key.
rows.forEach((e:HTMLElement) => keys.push(e.innerText.replace(/\s*/g,'')));
}
else {
// We craft dynamically item object.
let item: any = {};
keys.forEach((key, index) => {
// We use keys array to populate it.
item[key] = rows[index].innerHTML;
});
//We Store it
output.push(item);
}
});
console.log(output);
disclaimer :
This script assume you have only one tr with th inside AND is the first tr of your table. up to you to change this code to feet on another behaviour
Online sample
I am trying to sort the table data based on the column "Submitted Date" . I have written some code but it doesn't seem to be working. As I am new to Angular JS I need some guidance here. Please help.
code:
Angular js:
vm.sotData = function (column) {
vm.reverseSort = (vm.sortColumn == column) ? !vm.reverseSort : false;
vm.sortColumn = column;
}
Html Code:
<th style="width:13%" ng-click="">Total Amt<span ng-class=""></span></th>
<th style="width:7%" ng-click="">Status<span ng-class=""></span></th>
<th style="width:7%" ng-click="vm.sotData('SubmittedDate')">Submitted Date
<span ng-class="vm.getSortClass('SubmittedDate')"></span>
</th>
The main key of writing sorting functionality is to use
{{ orderBy_expression | orderBy : expression : reverse }}
This returns a sorted Array based on the item. You can change the sorting order by specifying the reverse parameter.
Let's take the example of below array
$scope.friends = [
{sno:1,name:'Yogesh Singh',age:23,gender:'Male'},
{sno:2,name:'Sonarika Bhadoria',age:23,gender:'Female'},
{sno:3,name:'Vishal Sahu',age:24,gender:'Male'},
{sno:4,name:'Sanjay Singh',age:22,gender:'Male'}
];
// column to sort
$scope.column = 'sno';
// sort ordering (Ascending or Descending). Set true for descending
$scope.reverse = false;
// called on header click
$scope.sortColumn = function(col){
$scope.column = col;
if($scope.reverse){
$scope.reverse = false;
$scope.reverseclass = 'arrow-up';
}else{
$scope.reverse = true;
$scope.reverseclass = 'arrow-down';
}
};
// remove and change class
$scope.sortClass = function(col){
if($scope.column == col ){
if($scope.reverse){
return 'arrow-down';
}else{
return 'arrow-up';
}
}else{
return '';
}
};
In html reverse is used for detecting ascending or descending ordering. The default value set to false for ascending.
<table border='1'>
<tr >
<th ng-click='sortColumn("sno")' ng-class='sortClass("sno")'>S.no</th>
<th ng-click='sortColumn("name")' ng-class='sortClass("name")'>Name</th>
<th ng-click='sortColumn("age")' ng-class='sortClass("age")'>Age</th>
<th ng-click='sortColumn("gender")' ng-class='sortClass("gender")'>Gender</th>
</tr>
<tr ng-repeat='friend in friends|orderBy:column:reverse'>
<td width='20%' align='center'>{{friend.sno}}</td>
<td width='35%' align='center'>{{friend.name}}</td>
<td width='20%' align='center'>{{friend.age}}</td>
<td width='25%' align='center'>{{friend.gender}}</td>
</tr>
</table>
<th style="width:13%" ng-click="">Total Amt<span ng-class=""></span></th>
<th style="width:7%" ng-click="">Status<span ng-class=""></span></th>
<th style="width:7%" ng-click="vm.sotData('SubmittedDate')">Submitted Date
<span class="fa" ng-class="{'fa-caret-down':sortType.type=='SubmittedDate' && sortType.order==-1 ,
'fa-caret-up':sortType.type=='SubmittedDate' && sortType.order==1}"> </span></th>
/*for sorting Column*/
$scope.vm.sotData= function (type) {
$scope.sortType.order = $scope.sortType.order === 1 ? -1 : 1;
if ($scope.sortType.order == '1') {
$scope.sortBy = type;
}
else {
$scope.sortBy = '-' + type;
}
};
Try this quick fix.
Code for sorting with Name in Friends
In your HTML,
1st change in table header for which sorting is to be done:-
<th style="width:7%" ng-click="orderByField='name'; reverseSort = !reverseSort"">Friend Name<span ng-class=""></span></th>
2nd change in table row
<tr ng-repeat="friend in Friends | orderBy:orderByField:reverseSort">....</tr>
I've below html.
<table border="1" class="myTable">
<tr>
<th class="cname">Component</th>
<th class="pname">Properties</th>
<th class="sname">lqwasb02</th>
</tr>
<tr>
<td class="cname">EMWBISConfig</td>
<td class="pname">reEvaluationTimer</td>
<td class="pvalue">every 1 hour without catch up</td>
</tr>
<tr>
<td class="cname">CalculateCategoryMediaInfoService</td>
<td class="pname">scheduled</td>
<td class="pvalue">yes</td>
</tr>
<tr>
<td class="cname">EMWBISScheduler</td>
<td class="pname">scheduled</td>
<td class="pvalue">no</td>
</tr>
<tr>
<td class="cname">CatalogTools</td>
<td class="pname">loggingDebug</td>
<td class="pvalue">false</td>
</tr>
</table>
Below is the jquery I've written.
$(document).ready(function(){
var list = ['every 1 hour without catch up','yes','yes','false'];
$.each(list,function(index,value){
//alert(index+' : '+value);
});
var idx;var list2 = new Array();
// Find index of cell with 'lqwasb02'
$('.myTable th').each(function(index) {
if ($(this).text() === 'lqwasb02') idx = index;
});
// Loop through each cell with the same index
$('.myTable tr').each(function() {
if($(this).find('td:eq('+idx+')').text() !=""){
list2.push($(this).find('td:eq('+idx+')').text());
}
}); var idx2 = [];
for(var x=0;x<list2.length;x++){
if(list[x]===list2[x]){
//console.log(list[x]);
}else{
console.log('mismatched : '+list[x]);
$('.myTable tr').each(function() {
$(this).find('td:eq('+x+')').css("background-color", "red");
});
idx2.push(x);
}
}
});
I'm trying to compare values in list with values in lqwasb02 column and if it finds the difference, it should highlight the background of td cell in red colour.
Current issue with jquery code, it is highlighting the complete column.
Can someone please help me where I'm getting wrong? If possible, please pass on the recommended solutions.
Many Thanks in advance.
The problem is that in your .find you are returning multiple elements that it's selector matches. So as opposed to storing the text value for your td elements in the second array, just store the actual td element, compare it's text, and then you can assign the background color directly to the element as opposed to finding it again via it's index:
$(document).ready(function(){
var list = ['every 1 hour without catch up','yes','yes','false'];
$.each(list,function(index,value){
//alert(index+' : '+value);
});
var idx;var list2 = new Array();
// Find index of cell with 'lqwasb02'
$('.myTable th').each(function(index) {
if ($(this).text() === 'lqwasb02') idx = index;
});
// Loop through each cell with the same index
$('.myTable tr').each(function() {
if($(this).find('td:eq('+idx+')').text() !=""){
list2.push($(this).find('td:eq('+idx+')')); // <-- Store the object here, not it's text value.
}
});
var idx2 = [];
for(var x=0; x < list2.length; x++){
if(list[x]===list2[x].text()) { // <-- compare list[x] to the text value of list2[x]
//console.log(list[x]);
} else {
list2[x].css("background-color", "red"); // <-- no find or selector needed, just apply it to the object you stored earlier.
};
idx2.push(x);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1" class="myTable">
<tr>
<th class="cname">Component</th>
<th class="pname">Properties</th>
<th class="sname">lqwasb02</th>
</tr>
<tr>
<td class="cname">EMWBISConfig</td>
<td class="pname">reEvaluationTimer</td>
<td class="pvalue">every 1 hour without catch up</td>
</tr>
<tr>
<td class="cname">CalculateCategoryMediaInfoService</td>
<td class="pname">scheduled</td>
<td class="pvalue">yes</td>
</tr>
<tr>
<td class="cname">EMWBISScheduler</td>
<td class="pname">scheduled</td>
<td class="pvalue">no</td>
</tr>
<tr>
<td class="cname">CatalogTools</td>
<td class="pname">loggingDebug</td>
<td class="pvalue">false</td>
</tr>
</table>
$('.myTable tr').each(function() {
$(this).find('td:eq('+x+')').css("background-color", "red");
});
this piece of code assign a background colour to each cell of index 'x' for each rows (each cells of index x of each table rows represent a column).
You have to select only the rows which contains the cells you want to colour.
Here is how i would have approached solving this issue:
$(document).ready(function(){
var list = ['every 1 hour without catch up','yes','yes','false'];
var colIndex = findColIndex('lqwasb02');
// Loop over table rows
$('tr').each(function(){
// Look up cell with specific index
var $cell = $(this).find('td').eq(colIndex);
// Check if the text of the cell is not present in the list and do smth
if ($.inArray($cell.text(), list) === -1) {
$cell.css('background', 'red')
}
});
});
// helper function to find the index of column by text in the header
function findColIndex (headerText) {
var $col = $('.myTable th:contains(' + headerText + ')');
return $('.myTable th').index($col);
}
https://jsbin.com/fafegi/1/edit?js,output
I have an HTML table and I want to iterate through its rows and create a collection or lets say an "array of objects".
For example:
<table id="tbPermission">
<tr>
<th>User ID</th>
<th>User Name</th>
</tr>
<tr>
<td>1</td>
<td>Test1</td>
</tr>
</table>
I want to create a collection as below:
var trArray = [];
$('#tbPermission tr').each(function () {
var tdArray = [];
$(this).find('td').each(function () {
// I want to create the array of objects here …
tdArray.push();
});
// Final array
trArray.push(tdArray);
});
The arrays may be like below:
tdArray : {'UserID' : '1', 'UserName' : 'Test1'};
and:
trArray : [
{'UserID' : '1', 'UserName' : 'Test1'},
{'UserID' : '2', 'UserName' : 'Test2'}
]
Try this code
var trArray = [];
$('#tbPermission tr').each(function () {
var tr =$(this).text(); //get current tr's text
var tdArray = [];
$(this).find('td').each(function () {
var td = $(this).text(); //get current td's text
var items = {}; //create an empty object
items[tr] = td; // add elements to object
tdArray.push(items); //push the object to array
});
});
Here, I just created an empty object, filled object with references of tr and td, the added that object to the final array.
adding a working jsfiddle
This solution relies on adding thead and tbody elements which is a good idea anyways since it indicates to the browser that the table actually is a "data" table and not presentational.
jQuery has a .map() function. map is a basic function where you take an array and then replace the values with a the return value of a callback function - which results in a new array.
$([1,4,9]).map(function(){ return Math.sqrt(this) });
// [1, 2, 3]
.toArray converts the array like jQuery object we get into a "true array".
jQuery(function(){
var $table = $("#tbPermission");
var headers = $table.find('thead th').map(function(){
return $(this).text().replace(' ', '');
});
var rows = $table.find('tbody tr').map(function(){
var result = {};
var values = $(this).find('>td').map(function(){
return $(this).text();
});
// use the headers for keys and td values for values
for (var i = 0; i < headers.length; i++) {
result[headers[i]] = values[i];
}
// If you are using Underscore/Lodash you could replace this with
// return _.object(headers, values);
return result;
}).toArray();
// just for demo purposes
$('#test').text(JSON.stringify(rows));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tbPermission">
<thead>
<tr>
<th>User ID</th>
<th>User Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Test1</td>
</tr>
</tbody>
</table>
<textarea id="test"></textarea>
If you for whatever reason cannot change the HTML you could use the index of the rows to differentiate between headers and rows of data:
var headers = $table.find('tr:eq(0) th').map(function(){
return $(this).text().replace(' ', '');
});
var rows = $table.find('tr:gt(0)').map(function(){
// ...
});
I would suggest changing your html slightly.
<table id="tbPermission">
<tr>
<th>User ID</th>
<th>User Name</th>
</tr>
<tr>
<td class="userid">1</td>
<td class="username">Test1</td>
</tr>
</table>
Then in your javascript when you want to get all the elements as an array you could do.
var userIdArray = $('#tbPermission .userid').map(function(userid){ return $(userid).html(); }).toArray();
This will find all elements with a class userid on the table, collect just the values, and .toArray() that result to get a basic javascript array. You can then take that and manipulate it into whatever json structure you want, or you could possibly create your json object inside that map function.
Check the console, you will get an array with the desired objects
var arr = [];
$('#tbPermission tr:not(.header)').each(function() {
var that = $(this);
var id = that.find('td').eq(0).text();
var name = that.find('td').eq(1).text();
var obj = { 'userId': id , 'userName': name };
arr.push(obj);
});
console.log(arr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id="tbPermission">
<tr class="header">
<th>User ID</th>
<th>User Name</th>
</tr>
<tr>
<td>1</td>
<td>Test1</td>
</tr>
<tr>
<td>2</td>
<td>Test2</td>
</tr>
</table>
It's a bit tricky based on the given structure. You may have to modify the HTML a bit to map cells to headers, like below.
var myArray = [];
$("#tbPermission").find("td").each(function() {
var $this = $(this), obj = {};
obj[$this.data("column")] = $this.text();
myArray.push(obj);
});
alert ( JSON.stringify(myArray) );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tbPermission">
<tr>
<th>User ID</th>
<th>User Name</th>
</tr>
<tr>
<td data-column="User ID">1</td>
<td data-column="User Name">Test1</td>
</tr>
</table>
Please give in some time to learn about Array.push() and Objects in Javascript. Hope that helps.
I have a table:
<table class="datatable" id="hosprates">
<caption> hospitalization rates test</caption> <thead>
<tr>
<th scope="col">Funding Source</th> <th scope="col">Alameda County</th> <th scope="col">California</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Medi-Cal</th>
<td>34.3</td>
<td>32.3</td>
</tr>
<tr>
<th scope="row">Private</th>
<td>32.2</td>
<td>34.2</td>
</tr>
<tr>
<th scope="row">Other</th>
<td>22.7</td>
<td>21.7</td>
</tr>
</tbody>
</table>
i want to retrieve column 1 and column 2 values per row as pairs that end up looking like this [funding,number],[funding,number]
i did this so far, but when i alert it, it only shows [object, object]...
var myfunding = $('#hosprates tbody tr').each(function(){
var funding = new Object();
funding.name = $('#hosprates tbody tr td:nth-child(1)').map(function() {
return $(this).text().match(/\S+/)[0];
}).get();
funding.value= $('#hosprates tbody tr td:nth-child(2)').map(function() {
return $(this).text().match(/\S+/)[0];
}).get();
});
alert (myfunding);
var result = $('#hosprates tbody').children().map(function () {
var children = $(this).children();
return {
name: children.eq(0).text(),
value: children.eq(1).text()
};
}).get();
This will build an array in the form:
[
{ name : "...", value: "..." },
{ name : "...", value: "..." },
{ name : "...", value: "..." }
]
etc
To get the name of the first row, use:
alert(result[0].name);
For the value:
alert(result[0].value);
Edit: if you want the result EXACTLY as you specify:
var result = $('#hosprates tbody').children().map(function () {
var children = $(this).children();
return "[" + children.eq(0).text() + "," + children.eq(1).text() + "]"
}).get().join(",");
Try this then (demo):
var funding = $('#hosprates tbody tr').map(function(){
return [[ $(this).find('th').eq(0).text() , // find first and only <th>
$(this).find('td').eq(0).text() ]]; // find first <td> in the row
}).get();
alert(funding); // Output: Medi-Cal,32.3,Private,34.2,Other,21.7
The alert display only shows the data inside the array, it is actually formatted like this:
[["Medi-Cal", "32.3"], ["Private", "34.2"], ["Other", "21.7"]]
So you could get the Medi-Cal data like this:
alert(funding[0][0] + ' -> ' + funding[0][1]); // output: Medi-Cal -> 34.3