How to display the search result from array of object in rxjs? - javascript

So I am using rxjs library and implementing my code using simple javascript. So I used ajax to make an API request for games and then mapped all the data inside the table, the table has the name of the game, released date, and genre. Now I have to only show the row based on the input search; basically, the user will search the game by name and only the data of that respective game will be shown in that particular row. How can we achieve such functionality using Rxjs?
I have added the snippet of the code.
Note: It takes 4-5 sec to fetch data.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.8.0/rxjs.umd.min.js"
integrity="sha512-v0/YVjBcbjLN6scjmmJN+h86koeB7JhY4/2YeyA5l+rTdtKLv0VbDBNJ32rxJpsaW1QGMd1Z16lsLOSGI38Rbg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>>
</head>
<body>
<h1>Games</h1>
<input type="text" name="" id="search_game" placeholder="search games">
<p id="test"></p>
<table cellpadding="10">
<thead>
<tr>
<th style="text-align:left;"id="game_name">Name</th>
<th style="text-align:left;">Released</th>
<th style="text-align:left;">Genre</th>
</tr>
<tbody id="table-content">
</tbody>
</thead>
</table>
</body>
<script>
const { of, fromEvent, ajax: { ajax }, operators: { startWith, switchMap, map, debounce }, combineLatest } = rxjs;
const searchGame = document.getElementById('search_game');
const search = fromEvent(searchGame, 'input');
search.subscribe(e=>console.log(e.target.value));
const games = ajax.getJSON('https://api.sampleapis.com/switch/games');
games.subscribe(gamesList => {
let tableContent = '';
gamesList.forEach(game => {
tableContent += `<tr>`;
tableContent += `<td>` + game.name + `</td>`
tableContent += `<td>` + (!game.releaseDates.Japan + ' ' + '(Japan)' ? game.releaseDates.Europe + ' ' + `(Europe)` : game.releaseDates.Australia + ' ' + `(Australia)`) + `</td>`
tableContent += `<td>` + game.genre + `</td>`
})
document.getElementById('table-content').innerHTML = tableContent
console.log(gamesList);
})
var x = document.getElementById('game_name').value;
</script>
</html>

You need to map the search to it's value and make it start with something so you don't need to press a key first.
const search = fromEvent(searchGame, 'input').pipe(
map(e => e.target.value),
startWith('')
);
then you can use combine latest on the two observables to filter the games to just the ones where the name contains the search string.
const { of, fromEvent, ajax: { ajax }, operators: { startWith, switchMap, map, debounce }, combineLatest } = rxjs;
const searchGame = document.getElementById('search_game');
const search = fromEvent(searchGame, 'input').pipe(
map(e => e.target.value),
startWith('') // Otherwise you wont get any results until you press a key
);
const games = ajax.getJSON('https://api.sampleapis.com/switch/games');
combineLatest([games, search]).pipe(
map(([games, search]) => games.filter(game => game.name.indexOf(search) !== -1))
)
.subscribe(gamesList => {
let tableContent = '';
gamesList.forEach(game => {
tableContent += `<tr>`;
tableContent += `<td>` + game.name + `</td>`
tableContent += `<td>` + (!game.releaseDates.Japan + ' ' + '(Japan)' ? game.releaseDates.Europe + ' ' + `(Europe)` : game.releaseDates.Australia + ' ' + `(Australia)`) + `</td>`
tableContent += `<td>` + game.genre + `</td>`
})
document.getElementById('table-content').innerHTML = tableContent
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.8.0/rxjs.umd.min.js"
integrity="sha512-v0/YVjBcbjLN6scjmmJN+h86koeB7JhY4/2YeyA5l+rTdtKLv0VbDBNJ32rxJpsaW1QGMd1Z16lsLOSGI38Rbg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<h1>Games</h1>
<input type="text" name="" id="search_game" placeholder="search games">
<p id="test"></p>
<table cellpadding="10">
<thead>
<tr>
<th style="text-align:left;"id="game_name">Name</th>
<th style="text-align:left;">Released</th>
<th style="text-align:left;">Genre</th>
</tr>
<tbody id="table-content">
</tbody>
</thead>
</table>

Related

Highlight Searched Text in Table bug

So I'm working on a feature that require a user to type in a search item that will search a table for the term and highlight every occurrence. I found some code and got it to work, but I have a bug that I'm not sure how to resolve. In the search input if I hit back space to erase the search term, the unhighlight works until the last character letter. For example, I type in Demo and use back space to delete Demo, only the D is still highlighted.
Below are my code snippets.
NOTE: I have a search and render function that call the highlightActivity and renderReports functions
My CSS
.highlight {
background-color :gold
}
.highlight {
padding:1px 4px;
margin: 0 -4px;
}
My HTML
<input type="text" id="uniStringSearch" onkeyup="SearchAndRender()"></input>
<table id="currentReports" class="table table-striped table-condensed table-bordered">
<thead>
<tr>
<th><input name="select_all" id="selectedReports" value="1" type="checkbox" onclick="checkAll(this)" /> </th>
<th>DATE</th>
<th>SUMMARY TITLE</th>
<th>NAME</th>
<th>ACTIVITY TYPE</th>
<th>SUB ACTIVITY TYPE</th>
<th>ACTIVITY DETAILS</th>
</tr>
</thead>
<tbody id="reports"></tbody>
</table>
HighlightActivity Function
function highlightActivity() {
var searchTerm = $('#uniStringSearch').val();
var tableID = ''
switch (webPage) {
case 'reports':
tableID = '#currentReports';
break;
case 'analysis':
tableID = '#currentAnalysis';
break;
case 'statuses':
tableID = '#currentStatuses';
break;
default:
}
$(tableID).find('.highlight').removeClass('highlight');
$(tableID).find('tr td').each(function () {
if ((this).attr('data-search') !== 'false') {
var text = $(this).text();
var textLowerCase = text.toLowerCase();
var pos = textLowerCase.indexOf(searchTerm.toLowerCase());
var regex = new RegExp(searchTerm, 'ig');
text = text.replace(regex, (match, $1) => {
return '<span class="highlight">' + match + '</span>';
});
$(this).html(text);
if (pos !== -1) {
setTimeout(function () {
if ($(this).parent().find('.highlight').is(':empty')) {
$('.highlight').remove();
}
}.bind(this), 0);
}
else {
$(this).text(text);
}
}
if ($(this).parent().find('.highlight').length > 0) {
$(this).parent().show();
}
else {
$(this).parent().hide();
}
});
}
Render Reports Function
function renderReports(items) {
var html = '';
for (var i = 0; i < items.length; i++)
{
html = '<tr><td><input type="checkbox" id="selectedReports" onchange="chkInputChanged(event)"/></td>'
html += '<td>' + items[i].DateActivity + '</td>'
html += '<td>' + items[i].Name + '</td>'
html += '<td>' + items[i].ActivityType + '</td>'
html += '<td>' + items[i].SubActivityType + '</td>'
html += '<td id="searchActivityDetails">' + items[i].ActivityDetails + '</td></tr>'
}
$('#reports').empty();
$('#reports').append(html);
}
ALSO....one more thing, is there a way to have my highlight function to target a specific column? For example Summary Title and Activity Details

Sorting table using only Javascript

I have this table in which I read the tbody contents from a JSON API and now I need to make it sortable by columns and using only javascript and no Jquery.
Any help would be appreciated
i have found this code which is exactly what i want, but i don't know how to refer to tbodies from my api
var myRequest = new XMLHttpRequest();
myRequest.open('GET', 'https://jsonplaceholder.typicode.com/todos');
myRequest.onload = function () {
var myData = JSON.parse(myRequest.responseText);
dataTable(myData);
};
myRequest.send();
function dataTable(data) {
if (data.length > 0) {
var temp = '';
data.forEach((u) => {
temp += '<tr>';
temp += "<td style='text-align: center'>" + u.userId + '</td>';
temp += "<td style='text-align: center'>" + u.id + '</td>';
temp += '<td>' + u.title + '</td>';
temp += "<td style='text-align: center'>" + u.completed + '</td></tr>';
document.getElementById('data').innerHTML = temp;
});
}
}
<table class="table_id">
<thead>
<tr>
<th>UserID</th>
<th>ID</th>
<th>Title</th>
<th>Completion</th>
</tr>
</thead>
<tbody id="data">
</tbody>
</table>
var myData, asc = {'userId':true, 'id':true, 'title':true, 'completed':true};
var myRequest = new XMLHttpRequest();
myRequest.open('GET', 'https://jsonplaceholder.typicode.com/todos');
myRequest.onload = function () {
myData = JSON.parse(myRequest.responseText);
dataTable(myData);
};
myRequest.send();
function sortTable(key){
myData.sort(function(a, b) {
if(asc[key]){
return a[key] > b[key]? 1:-1;
}
else{
return a[key] > b[key]? -1:1;;
}
});
asc[key] = !asc[key];
document.getElementById('data').innerHTML = '';
dataTable(myData);
}
function dataTable(data) {
if (data.length > 0) {
var temp = '';
data.forEach((u) => {
temp += '<tr>';
temp += "<td style='text-align: center'>" + u.userId + '</td>';
temp += "<td style='text-align: center'>" + u.id + '</td>';
temp += '<td>' + u.title + '</td>';
temp += "<td style='text-align: center'>" + u.completed + '</td></tr>';
document.getElementById('data').innerHTML = temp;
});
}
}
<table class="table_id">
<thead>
<tr>
<th onclick="sortTable('userId');">UserID</th>
<th onclick="sortTable('id');">ID</th>
<th onclick="sortTable('title');">Title</th>
<th onclick="sortTable('completed');">Completion</th>
</tr>
</thead>
<tbody id="data">
</tbody>
</table>
Here is a quick class I made.
You first load your data with dt.load(), then when someone clicks one of the headers, you can add an event that does:
elm.addEventListener("click", (e) => {
prop = e.target.textContent.trim();
dt.sort(prop);
dt.render();
})
class DataTable{
load(arr){
if(arr) this.data = arr;
}
sort(prop){
this.data.sort((a, b) => a[prop] - b[prop]);
}
render(selector="#data"){
if(data.length){
html = data.map(u => {
return [
"<tr>",
`<td style='text-align: center'>${u.userId}</td>`,
`<td style='text-align: center'>${u.id}</td>`,
`<td>${u.title}</td>`,
`<td style='text-align: center'>${u.completed}</td></tr>`
].join("");
}).join("");
document.querySelector(selector).innerHTML = html;
}
}
}
Important - are you wanting to be able to sort multiple columns at the same time or just one column at a time?
Initialize myData outside of onload first. You'll want to be able to access those results outside of onload to sort them. The actual sort function JS offers is a pretty confusing but it's really the only way to go about vanilla JS array sorting.
function sortData(col, asc = true) {
//JS sort function
myData = myData.sort((first, second) => {
//sort logic
if (first[col] == second[col]) {
return 0;
}
if (asc) {
if (first[col] > second[col]) {
return 1;
}
else {
return -1;
}
}
else {
if (first[col] > second[col]) {
return -1;
}
else {
return 1;
}
}
});
//Re-Create table
dataTable(myData);
}
EDIT:
I added in sort logic, but it's definitely possible I messed up. I can't actually test this right now and I haven't touched the sort function in years.

How can I add buttons REMOVE and EDIT to my table?

It is my teacher table in index.html which displayed only after click on button Teachers :
<div class="container">
<table class="teacherTable" border="1" width="100%" cellpadding="5">
<thead>
<th>TEACHER ID</th>
<th>TEACHER NAME</th>
<th>TEACHER POSITION</th>
<tbody id="teacherBody">
</tbody>
</table>
</div>
because I have in my styles :
<style>
.container table {
display: none;
}
</style>
And here is my getTeachers.js file :
GET: $(document).ready(
function () {
// GET REQUEST
$("#getAllTeachers").click(function (event) {
event.preventDefault();
ajaxGet();
});
// DO GET
function ajaxGet() {
$.ajax({
type: "GET",
url: "checkTeachers",
success: function (result) {
if (result.status == "success") {
var custList = "";
$.each(result.data,
function (i, teacher) {
var Html = "<tr>" +
"<td>" + teacher.teacherId + "</td>" +
"<td>" + teacher.teacherName + "</td>" +
"<td>" + teacher.position + "</td>" +
"<td>" + 'X' + "</td>" +
"</tr>";
console.log("Teacher checking: ", teacher);
$('#teacherBody').append(Html);
$('#groupBody').empty();
$('.groupTable').hide();
$('.teacherTable').show();
});
console.log("Success: ", result);
} else {
console.log("Fail: ", result);
}
},
error: function (e) {
console.log("ERROR: ", e);
}
});
}
})
And also in index.html I have this button for looking for all teachers in my database :
<button id="getAllTeachers" type="button" class="btn btn-primary">Teachers</button>
So, my question is how to add one more or two fields to my table which should be called REMOVE and EDIT.
I saw some solutions but I have no idea how to use it with my js file.
Maybe I can use bootstrap for it or do it manually..
Created a snippet to show you a possible way to solve the question. I used a "placeholder API" to simulate your code (so there's no "position", instead I used username).
The edit function is just mocked here - that can have so many possible directions, that I didn't want to elaborate the function.
// fetching the data from the API
const fetchAllTeachers = async() => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users')
const json = await response.json()
return json
} catch (err) {
console.error(err)
return []
}
}
// data array for teachers
let teachers = []
// table row "template"
const tableRowHTML = (teacher) => {
const {
id,
name,
username
} = teacher // this is source-dependent
let html = ''
html += `<tr>`
html += `<td>${ id }</td>`
html += `<td>${ name }</td>`
html += `<td>${ username }</td>`
html += `<td><button data-editid="${ id }">EDIT</button></td>`
html += `<td><button data-removeid="${ id }">REMOVE</button></td>`
html += `</tr>`
return html
}
// updating table
const updateTable = (teachers) => {
const tableBody = jQuery('#teacherBody')
let html = ''
teachers.forEach(teacher => {
html += tableRowHTML(teacher)
})
tableBody.html(html)
}
// jQuery action bindings
jQuery(document).ready(function($) {
$('#fetchAllTeachers').on('click', async function() {
teachers = await fetchAllTeachers()
updateTable(teachers)
})
$('body').on('click', '[data-removeid]', function() {
teachers = removeTeacher(this.getAttribute('data-removeid'), teachers)
updateTable(teachers)
})
$('body').on('click', '[data-editid]', function() {
teachers = editTeacher(this.getAttribute('data-editid'), teachers)
updateTable(teachers)
})
})
// remove action
const removeTeacher = (id, teachers) => {
const teacher = teachers.find(({
id: tId
}) => tId == id)
let ret = [...teachers]
if (ret.indexOf(teacher) !== -1) {
ret.splice(teachers.indexOf(teacher), 1);
}
return ret
}
// edit action
const editTeacher = (id, teachers) => {
let ret = [...teachers]
console.log('create the edit feature; teacher ID:', id)
return ret
}
table {
border-collapse: collapse;
}
.container table {
/*display: none;*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<button id="fetchAllTeachers">GET ALL TEACHERS</button>
<table class="teacherTable" border="1" width="100%" cellpadding="5">
<thead>
<th>TEACHER ID</th>
<th>TEACHER NAME</th>
<th>TEACHER POSITION</th>
<th colspan="2"></th>
<tbody id="teacherBody"></tbody>
</table>
</div>

Create the table with json data

I want to create a table with json response and I used reduce function to parse the array.I'm getting reduce not a function error.I want to make the table header as colModels title as header and data of 'Arvind partha','Us West' and so on as td body.
const response={"leads":{"data":[{"UserName":"Arvind Partha","Geo":"US West","LeadStage":"SGL","Firstname":"Julie","Lastname":"Daly","CompanyName":"","Region":"North America","JobTitle":"VP Digital Commerce","Theme":"Digital Retail - Re-Inventing In-Sotre experience","Department":"","Designation":"Vice president","TargetSource":"Database","Medium":"Email","Status":"New","DigitalMarketingOwner":"kishore.natarajan","MQLCallingOwner":"","Practice":"Retail","ServiceLine":"Retail","datecreated":"02-Jun-2020","datemodified":"02-Jun-2020"},{"UserName":"Harish Rajagopalan","Geo":"US West","LeadStage":"MGL","Firstname":"preeti","Lastname":"viswanath","CompanyName":"","Region":"North America","JobTitle":"","Theme":"Oracle Retail - Maximize business value out of oracle retail solutions","Department":"","Designation":"Manager","TargetSource":"","Medium":"","Status":"New","DigitalMarketingOwner":"","MQLCallingOwner":"","Practice":"Retail","ServiceLine":"Retail","datecreated":"17-Jun-2020","datemodified":"18-Jun-2020"}],"ColModels":[{"data":"UserName","title":"User Name"},{"data":"Geo","title":"Geo"},{"data":"LeadStage","title":"Lead Stage"},{"data":"Firstname","title":"First Name"},{"data":"Lastname","title":"Last Name"},{"data":"CompanyName","title":"Company Name"},{"data":"Region","title":"Region"},{"data":"JobTitle","title":"Job Title"},{"data":"Theme","title":"Theme"},{"data":"Department","title":"Department"},{"data":"Designation","title":"Designation"},{"data":"TargetSource","title":"Target Source"},{"data":"Medium","title":"Medium"},{"data":"Status","title":"Status"},{"data":"DigitalMarketingOwner","title":"Digital Marketing Owner"},{"data":"MQLCallingOwner","title":"MQL Calling Owner"},{"data":"Practice","title":"Practice"},{"data":"ServiceLine","title":"Service Line\/Vertical"},{"data":"datecreated","title":"Date Created","formatter":"date","formatoptions":{"newformat":"d-M-yy"}},{"data":"datemodified","title":"Date Modified"}],"types":{"RGL":"RGL","SGL":"Named Lead","MGL":"SAL","PGL":"PGL","BGL":"BGL","Back to marketing":"Back to marketing","Uncategorized lead":""}},"meetings":{"data":[],"ColModels":[{"data":"UserName","title":"User Name"},{"data":"Geo","title":"Geo"},{"data":"RelatedTo","title":"Related to"},{"data":"Subject","title":"Subject"},{"data":"Description","title":"Description"},{"data":"Status","title":"Status"},{"data":"MeetingType","title":"Meeting Type"},{"data":"MeetingHash","title":"Meeting #"},{"data":"Location","title":"Location"},{"data":"startdate","title":"Start Date"},{"data":"enddate","title":"End Date"},{"data":"DurationHours","title":"Duration Hours"},{"data":"DurationMinutes","title":"Duration Minutes"},{"data":"datecreated","title":"Date Created"},{"data":"datemodified","title":"Date Modified"}],"types":{"1st Presentation \/ Meeting":"first_time","Follow-On Meetings":"follow_up","Hold\/Uncategorized":""}},"opportunity":{"data":[],"ColModels":[{"data":"Username","title":"User Name"},{"data":"Geo","title":"Geo"},{"data":"OpportunityGeo","title":"Opportunity Geo"},{"data":"CompanyName","title":"Company Name"},{"data":"SalesStage","title":"Sales Stage"},{"data":"Probability","title":"Probability (%)"},{"data":"PipelineValue","title":"Pipeline Value"},{"data":"CustomerAccountType","title":"Customer Account Type"},{"data":"OpportunityType","title":"Opportunity Type"},{"data":"TeamType","title":"Team Type"},{"data":"LeadSource","title":"Lead Source"},{"data":"ServiceLine","title":"Service Line\/Vertical"},{"data":"datecreated","title":"Date Created"},{"data":"datemodified","title":"Date Modified"},{"data":"salesstagelastmodified","title":"Sales Stage Last Modified"}],"types":{"Identified Opportunities":"Identified","QO under evaluation":"QO_to be approved"}},"reaches":{"data":[],"ColModels":[{"data":"Username","title":"User Name"},{"data":"Geo","title":"Geo"},{"data":"Subject","title":"Subject"},{"data":"Description","title":"Description"},{"data":"Relatedto","title":"Related To"},{"data":"Calloutcome","title":"Call out come"},{"data":"Status","title":"Status"},{"data":"startdate","title":"Start Date"},{"data":"enddate","title":"End Date"},{"data":"Duration","title":"Duration"},{"data":"datecreated","title":"Date Created"},{"data":"datemodified","title":"Date Modified"}],"types":{"Reaches":"Reaches"}},"activities":{"data":[],"ColModels":[{"data":"Username","title":"User Name"},{"data":"Geo","title":"Geo"},{"data":"Subject","title":"Subject"},{"data":"Description","title":"Description"},{"data":"Relatedto","title":"Related To"},{"data":"From","title":"From"},{"data":"datesent","title":"Date Sent"},{"data":"Status","title":"Status"},{"data":"datecreated","title":"Date Created"},{"data":"datemodified","title":"Date Modified"}],"types":{"Activities":"Activities"}},"category":{"leads":{"RGL":"RGL","SGL":"Named Lead","MGL":"SAL","PGL":"PGL","BGL":"BGL","Back to marketing":"Back to marketing","Uncategorized lead":""},"meeting":{"1st Presentation \/ Meeting":"first_time","Follow-On Meetings":"follow_up","Hold\/Uncategorized":""},"opportunity":{"Identified Opportunities":"Identified","QO under evaluation":"QO_to be approved"},"reaches":{"Reaches":"Reaches"},"activities":{"Activities":"Activities"}},"Month":["June-2020"],"Week":["Week 1","Week 2","Week 3","Week 4"],"Team":null};
if((response.leads.data).length) {
var colModels = response.leads.ColModels;
var data = response.leads.data;
console.log(colModels);
console.log(data);
console.log(colModels.title);
colModels.forEach(tr => {
console.log(tr.title);
const thString = tr.title.reduce((res, d) => res + '<td>' + d + '</td>', "");
//$('#tbody').append("<tr>" + trString + "</tr>");
});
$('#thead').html(thString);
data.forEach(tr => {
const trString = tr.data.reduce((res, d) => res + '<td>' + d + '</td>', "");
$('#tbody').append("<tr>" + trString + "</tr>");
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead id="thead"></thead>
<tbody id="tbody"></tbody>
</table>
To achieve expected result, use below option of string concatenation instead of reduce function
Issue from your code is, below mentioned tr is object and reduce works only for arrays.
Removed reduce function and added string concatenation using variable 'head'
let head = '<tr>';
colModels.forEach(tr => {
console.log("tr", tr);
head = head + '<td>' + tr.title + '</td>';
});
Other reduce function is also trying to loop through object instead of array and fixed that using Object.entries
data.forEach((tr) => {
const trString = Object.entries(tr).reduce(
(res, d) => res + "<td>" + d[1] + "</td>",
""
);
$("#tbody").append("<tr>" + trString + "</tr>");
});
Working code for reference
const response={"leads":{"data":[{"UserName":"Arvind Partha","Geo":"US West","LeadStage":"SGL","Firstname":"Julie","Lastname":"Daly","CompanyName":"","Region":"North America","JobTitle":"VP Digital Commerce","Theme":"Digital Retail - Re-Inventing In-Sotre experience","Department":"","Designation":"Vice president","TargetSource":"Database","Medium":"Email","Status":"New","DigitalMarketingOwner":"kishore.natarajan","MQLCallingOwner":"","Practice":"Retail","ServiceLine":"Retail","datecreated":"02-Jun-2020","datemodified":"02-Jun-2020"},{"UserName":"Harish Rajagopalan","Geo":"US West","LeadStage":"MGL","Firstname":"preeti","Lastname":"viswanath","CompanyName":"","Region":"North America","JobTitle":"","Theme":"Oracle Retail - Maximize business value out of oracle retail solutions","Department":"","Designation":"Manager","TargetSource":"","Medium":"","Status":"New","DigitalMarketingOwner":"","MQLCallingOwner":"","Practice":"Retail","ServiceLine":"Retail","datecreated":"17-Jun-2020","datemodified":"18-Jun-2020"}],"ColModels":[{"data":"UserName","title":"User Name"},{"data":"Geo","title":"Geo"},{"data":"LeadStage","title":"Lead Stage"},{"data":"Firstname","title":"First Name"},{"data":"Lastname","title":"Last Name"},{"data":"CompanyName","title":"Company Name"},{"data":"Region","title":"Region"},{"data":"JobTitle","title":"Job Title"},{"data":"Theme","title":"Theme"},{"data":"Department","title":"Department"},{"data":"Designation","title":"Designation"},{"data":"TargetSource","title":"Target Source"},{"data":"Medium","title":"Medium"},{"data":"Status","title":"Status"},{"data":"DigitalMarketingOwner","title":"Digital Marketing Owner"},{"data":"MQLCallingOwner","title":"MQL Calling Owner"},{"data":"Practice","title":"Practice"},{"data":"ServiceLine","title":"Service Line\/Vertical"},{"data":"datecreated","title":"Date Created","formatter":"date","formatoptions":{"newformat":"d-M-yy"}},{"data":"datemodified","title":"Date Modified"}],"types":{"RGL":"RGL","SGL":"Named Lead","MGL":"SAL","PGL":"PGL","BGL":"BGL","Back to marketing":"Back to marketing","Uncategorized lead":""}},"meetings":{"data":[],"ColModels":[{"data":"UserName","title":"User Name"},{"data":"Geo","title":"Geo"},{"data":"RelatedTo","title":"Related to"},{"data":"Subject","title":"Subject"},{"data":"Description","title":"Description"},{"data":"Status","title":"Status"},{"data":"MeetingType","title":"Meeting Type"},{"data":"MeetingHash","title":"Meeting #"},{"data":"Location","title":"Location"},{"data":"startdate","title":"Start Date"},{"data":"enddate","title":"End Date"},{"data":"DurationHours","title":"Duration Hours"},{"data":"DurationMinutes","title":"Duration Minutes"},{"data":"datecreated","title":"Date Created"},{"data":"datemodified","title":"Date Modified"}],"types":{"1st Presentation \/ Meeting":"first_time","Follow-On Meetings":"follow_up","Hold\/Uncategorized":""}},"opportunity":{"data":[],"ColModels":[{"data":"Username","title":"User Name"},{"data":"Geo","title":"Geo"},{"data":"OpportunityGeo","title":"Opportunity Geo"},{"data":"CompanyName","title":"Company Name"},{"data":"SalesStage","title":"Sales Stage"},{"data":"Probability","title":"Probability (%)"},{"data":"PipelineValue","title":"Pipeline Value"},{"data":"CustomerAccountType","title":"Customer Account Type"},{"data":"OpportunityType","title":"Opportunity Type"},{"data":"TeamType","title":"Team Type"},{"data":"LeadSource","title":"Lead Source"},{"data":"ServiceLine","title":"Service Line\/Vertical"},{"data":"datecreated","title":"Date Created"},{"data":"datemodified","title":"Date Modified"},{"data":"salesstagelastmodified","title":"Sales Stage Last Modified"}],"types":{"Identified Opportunities":"Identified","QO under evaluation":"QO_to be approved"}},"reaches":{"data":[],"ColModels":[{"data":"Username","title":"User Name"},{"data":"Geo","title":"Geo"},{"data":"Subject","title":"Subject"},{"data":"Description","title":"Description"},{"data":"Relatedto","title":"Related To"},{"data":"Calloutcome","title":"Call out come"},{"data":"Status","title":"Status"},{"data":"startdate","title":"Start Date"},{"data":"enddate","title":"End Date"},{"data":"Duration","title":"Duration"},{"data":"datecreated","title":"Date Created"},{"data":"datemodified","title":"Date Modified"}],"types":{"Reaches":"Reaches"}},"activities":{"data":[],"ColModels":[{"data":"Username","title":"User Name"},{"data":"Geo","title":"Geo"},{"data":"Subject","title":"Subject"},{"data":"Description","title":"Description"},{"data":"Relatedto","title":"Related To"},{"data":"From","title":"From"},{"data":"datesent","title":"Date Sent"},{"data":"Status","title":"Status"},{"data":"datecreated","title":"Date Created"},{"data":"datemodified","title":"Date Modified"}],"types":{"Activities":"Activities"}},"category":{"leads":{"RGL":"RGL","SGL":"Named Lead","MGL":"SAL","PGL":"PGL","BGL":"BGL","Back to marketing":"Back to marketing","Uncategorized lead":""},"meeting":{"1st Presentation \/ Meeting":"first_time","Follow-On Meetings":"follow_up","Hold\/Uncategorized":""},"opportunity":{"Identified Opportunities":"Identified","QO under evaluation":"QO_to be approved"},"reaches":{"Reaches":"Reaches"},"activities":{"Activities":"Activities"}},"Month":["June-2020"],"Week":["Week 1","Week 2","Week 3","Week 4"],"Team":null};
if((response.leads.data).length) {
var colModels = response.leads.ColModels;
var data = response.leads.data;
console.log('colModels', colModels);
console.log("data", data);
console.log(colModels.title);
let head = '<tr>'
colModels.forEach(tr => {
console.log("tr", tr);
head = head + '<td>' + tr.title + '</td>';
});
$('#thead').html(head + '</tr>');
data.forEach(tr => {
const trString = Object.entries(tr).reduce((res, d) => res + '<td>' + d[1] + '</td>', "");
$('#tbody').append("<tr>" + trString + "</tr>");
});
}
table, tr, td, th{
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead id="thead"></thead>
<tbody id="tbody"></tbody>
</table>
Codepen for reference - https://codepen.io/nagasai/pen/qBbxJrj

Using Firestore's snapshot.forEach to create a table

I'm trying to output an array filled with Firestore objects onto a table, but just displays the last object above the table
<table class="darkTable">
<thead>
<tr>
<th>List of Available Shows</th>
</tr>
</thead>
<tbody>
<tr>
<div id="showList"></div>
</tr>
</tbody>
</table>
<script>
firebase.firestore().collection('TV Shows').get().then(snapshot => {
var i = 0;
var array = [];
snapshot.forEach(doc => {
array[i] = doc.data().show.name;
//console.log(doc.data().show.name);
//showList.innerHTML = array[i] + "<br />";
showList.innerHTML = '<td>' + array[i] + '</td>';
i++;
});
});
</script>
Is it the way I'm going about the td code lines?
assuming this markup:
<div id="showList"></div>
then it works about like this:
firebase.firestore().collection('TV Shows').get().then(snapshot => {
var showList = document.getElementById('showList');
var html = '<table class="darkTable"><thead><tr>';
html += '<th>List of Available Shows</th>';
/* add further columns into here, alike the one above. */
html += '</tr></thead><tbody>';
snapshot.forEach(doc => {
html += '<tr>';
html += '<td>' + doc.data().show.name + '</td>';
/* add further columns into here, alike the one above. */
html += '</tr>';
});
html += '</tbody></table>';
showList.append(html);
});
You're resetting the entire showList element with every iteration of the loop:
showList.innerHTML = '<td>' + array[i] + '</td>';
I suspect you mean to append to it each time instead or resetting it entirely each time. Maybe try building a string with each iteration, then set the whole thing after the loop is over.

Categories

Resources