0

Here is my json APi -- >>> https://api.myjson.com/bins/p18mi

I have a table in which I have to print the Json data.

The problem is I want to print the Question data in major Question header and User_info array in thofUser column.

But its not working as expected. I am not able to arrange the table data properly so that all the user details must come User column and sub column. Same for question.

The output i am getting is this is image

enter image description here

$(function() {
  var people = [];
  $.getJSON('https://api.myjson.com/bins/p18mi', function(data) {
    $.each(data.ct_info, function(i, f) {
      var tblRow = " <tr>" + `<td id=${f.id}>` + `${f.id}` + "</td>" +
        "<td>" + f.name + "</td>";
      $(tblRow).appendTo("#userdata tbody");
      var users = []
      var question = []
      f.Qid_info.forEach((x) => {
        x.user_info.forEach((y) => {
          //avoid duplicates
          var foundUser = users.find((user) => {
            return user.id === y.id
          })
          if (!foundUser) {
            users.push(y)
          }
        })
      })
      f.Qid_info.forEach((x) => {
        var foundQuestion = question.find((questions) => {
          return questions.id === x.id
        })
        if (!foundQuestion) {
          question.push(x)
        }
      })
      $.each(question, function(i, question) {
        var questionRow = `<td id=${question.id}>` + `${question.id}` +
          "</td>" + "<td>" + question.isActive + "</td><td>" + question.iscomplex + "</td>" +
          "<td>" + question.isbreakdown + "</td>"
        $(questionRow).appendTo("#userdata tbody");
      })
      $.each(users, function(i, user) {
        var userRow = `<td id=${user.id}>` + `${user.id}` +
          "</td>" + "<td>" + user.name + "</td><td>" + user.data + "</td>" +
          "<td>" + user.updatedAt + "</td>"
        $(userRow).appendTo("#userdata tbody");
      })
    });
  });
});
#user {
  overflow-x: auto;
  white-space: nowrap;
}

th,
td {
  font-weight: normal;
  padding: 5px;
  text-align: center;
  width: 120px;
  vertical-align: top;
}

th {
  background: #00B0F0;
}

tr+tr th,
tbody th {
  background: #DAEEF3;
}

tr+tr,
tbody {
  text-align: left
}

table,
th,
td {
  border: solid 1px;
  border-collapse: collapse;
  table-layout: fixed;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id='userdata'>
  <tr>
    <th colspan="2" id="ct">CT INFO</th>
    <th colspan="4" id="que">Question</th>
    <th colspan="4" id="user">User Info</th>
  </tr>
  <tr>
    <th>CT ID</th>
    <th>CT</th>
    <th>Id</th>
    <th>isActive</th>
    <th>is Complex</th>
    <th>is Breakdown</th>
    <th>ID</th>
    <th>NAME</th>
    <th>Data</th>
    <th>updatedAt</th>
  </tr>
  <tbody>

  </tbody>
</table>

2
  • I clicked edit, then [<>] and created you a minimal reproducible example Commented Nov 19, 2019 at 6:50
  • Thankyou for doing that. I see it is more clear to read and answer now Commented Nov 19, 2019 at 6:52

2 Answers 2

2

Start by using the template literal correctly and then realise you cannot append some unfinished row.

Also you need a thead, or the browser will insert an extra tbody

You need to add a colspanned cell for ct for each question and each user and add a colspanned cell for each question to the user.

It could be done with rowspan but that is up to you now.

Lastly your keys are "is complex" and "is breakdown"

$(function() {
  var people = [];
  var ctCells = [], questionCells = [], userCells = [];
  var $tBody = $("#userdata tbody");
  $.getJSON('https://api.myjson.com/bins/p18mi', function(data) {
    $.each(data.ct_info, function(i, f) {
      ctCells.push(`<td id=${f.id}>${f.id}</td><td>${f.name}</td>`);
      var users = []
      var question = []
      f.Qid_info.forEach((x) => {
        x.user_info.forEach((y) => {
          //avoid duplicates
          var foundUser = users.find((user) => {
            return user.id === y.id
          })
          if (!foundUser) {
            users.push(y)
          }
        })
      })
      f.Qid_info.forEach((x) => {
        var foundQuestion = question.find((questions) => {
          return questions.id === x.id
        })
        if (!foundQuestion) {
          question.push(x)
        }
      })
      $.each(question, function(i, question) {
        ctCells.push(`<td colspan="2">&nbsp;</td>`)
        questionCells.push(`<td id=${question.id}>${question.id}</td><td>${question.isActive}</td><td>${question["is complex"]}</td><td>${question["is breakdown"]}</td>`);
        
      })
      $.each(users, function(i, user) {
        ctCells.push(`<td colspan="2">&nbsp;</td>`)
        questionCells.push(`<td colspan="4">&nbsp;</td>`)
        userCells.push(`<td id=${user.id}>${user.id}</td><td>${user.name}</td><td>${user.data}</td><td>${user.updatedAt}</td>`);
      })
    });
    $.each(userCells,function(i) {
      $tBody.append(`<tr>${ctCells[i]}${questionCells[i]}${userCells[i]}</tr>`)
    })
  });
});
#user {
  overflow-x: auto;
  white-space: nowrap;
}

th,
td {
  font-weight: normal;
  padding: 5px;
  text-align: center;
  width: 120px;
  vertical-align: top;
}

th {
  background: #00B0F0;
}

tr+tr th,
tbody th {
  background: #DAEEF3;
}

tr+tr,
tbody {
  text-align: left
}

table,
th,
td {
  border: solid 1px;
  border-collapse: collapse;
  table-layout: fixed;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id='userdata'>
  <thead>
  <tr>
    <th colspan="2" id="ct">CT INFO</th>
    <th colspan="4" id="que">Question</th>
    <th colspan="4" id="user">User Info</th>
  </tr>
  <tr>
    <th>CT ID</th>
    <th>CT</th>
    <th>Id</th>
    <th>isActive</th>
    <th>is Complex</th>
    <th>is Breakdown</th>
    <th>ID</th>
    <th>NAME</th>
    <th>Data</th>
    <th>updatedAt</th>
  </tr>
  </thead>
  <tbody>

  </tbody>
</table>

Sign up to request clarification or add additional context in comments.

9 Comments

yes..one more thing...i why this data is printing two times
Because your table was not valid HTML. The browser inserted another tbody and I updated both. Now it works. See the changed table
Yes its structure is perfect now. But what about the other data of user listed in Json. Your code is just rendering only one object of Userinfo and QuestionInfo
I also fixed your undefined "is complex" and "is breakdown"
You can surely do the rest now?
|
1

A general idea is to decouple the logic from the printing.

In that case,

  1. parse the json as an array (a matrix for that matter)
  2. then print your array.

Advantages are amongst:

  • you can test your "extracting"
  • you can also chose to display differently as done below

  1. To parse the json

    • every user is a row
    • and in front of some of them, prepend the question, and eventually the ct_info (or blanks otherwise)
  2. To print the array

    • either print all tds, and apply css afterwards

You can use td:empty{border:0;}. See that SO link

  • Or brutally merge the empty tds in front of the row as inline colspan

$(function() {
	var people = [];
	function myJsonTable(data){
		function pushFront(fields){
			return function(x,i){
				if(i==0) return (x.unshift(...fields),x);
				return (x.unshift(...fields.map(_=>'')),x);
			}
		}
		return data.ct_info.reduce((rows, ct_info,i)=>{
			let questionUsers = ct_info.Qid_info.reduce((acc, question)=>{
				let users = question.user_info.map(({id, name, data, updatedAt})=>{
					return [id, name, data.join(','), updatedAt]
				});
				//for each user
				//[user, user, user]
				//consider its transpose 
				//[[...user]
				// [...user]
				// [...user]
				// ]
				// and prepend the question on first column
				// you obviously have to spread everything, this is just for illustration purpose
				// [[question, user]
				//  [[]  	 , user]
				//  [[] 	 , user]
				let q = [question.id, question.isActive, question['is complexe'], question['is breakdown']]
				return acc.concat(users.map(pushFront(q)));
			},[]);

			//do the same for each info
			// [[info1, question, user]
			//  [[],    []      , user]
			//  [[],    question, user]
			//  [[],    []      , user]
			//  [info2, question, user]
			//  [[],    []      , user]
			// ]
			return rows.concat(questionUsers.map(pushFront([ct_info.id, ct_info.name])))
		},[]);
	}
	$.getJSON('https://api.myjson.com/bins/p18mi', function(data) {
		let table = myJsonTable(data);
		let dom = table.map(row=>'<tr>'+row.map(cell=>`<td>${cell}</td>`).join('')+'</tr>');
		$('table:eq(0) tbody').append(dom);

		let dom1 = table.map(row=>{
			let idx = row.findIndex(cell=>cell!='');
			let tds = row.slice(idx).map(cell=>`<td>${cell}</td>`).join('')
			let colspan = idx>0? `<td colspan="${idx}"></colspan>`:'';
			return `<tr>${colspan}</td>${tds}</tr>`;
		});
		$('table:eq(1) tbody').append(dom1);
	});
});
#user {
	overflow-x: auto;
	white-space: nowrap;
}

th,
td {
	font-weight: normal;
	padding: 5px;
	text-align: center;
	width: 120px;
	vertical-align: top;
}

th {
	background: #00B0F0;
}

tr+tr th,
tbody th {
	background: #DAEEF3;
}

tr+tr,
tbody {
	text-align: left
}
table,
th,
td {
	border: solid 1px;
	table-layout: fixed;
}
/* --------------------- */
table{
	border-collapse: collapse;
	/*empty-cells:hide; cannot use if border-collapse!=separate, setting separate with border-spacing:0 makes ugly borders*/
}
/*https://stackoverflow.com/questions/18758373/why-do-the-css-property-border-collapse-and-empty-cells-conflict*/
td:empty{
	border:0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
css
<table id='userdata'>
	<thead>
		<tr>
			<th colspan="2" id="ct">CT INFO</th>
			<th colspan="4" id="que">Question</th>
			<th colspan="4" id="user">User Info</th>
		</tr>
		<tr>
			<th>CT ID</th>
			<th>CT</th>
			<th>Id</th>
			<th>isActive</th>
			<th>is Complex</th>
			<th>is Breakdown</th>
			<th>ID</th>
			<th>NAME</th>
			<th>Data</th>
			<th>updatedAt</th>
		</tr>
	</thead>
	<tbody>

	</tbody>
</table>
<hr/>
inline colspan
<table id='userdata'>
	<thead>
		<tr>
			<th colspan="2" id="ct">CT INFO</th>
			<th colspan="4" id="que">Question</th>
			<th colspan="4" id="user">User Info</th>
		</tr>
		<tr>
			<th>CT ID</th>
			<th>CT</th>
			<th>Id</th>
			<th>isActive</th>
			<th>is Complex</th>
			<th>is Breakdown</th>
			<th>ID</th>
			<th>NAME</th>
			<th>Data</th>
			<th>updatedAt</th>
		</tr>
	</thead>
	<tbody>

	</tbody>
</table>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.