I'm new to javascript and trying to achieve one thing. I have on my site's table with TD's fetched from API URL by code bellow, with the result as on the image below.
What I'm trying to achieve is to make TD's clickable and an onclick redirects to another page where fetch URL will change from https://api.ulozenka.cz/v3/consignments to https://api.ulozenka.cz/v3/consignments/id (id from first td array), or at least onlick redirect to another page and store id from current td first array to variable (PHP variable will be better if it's possible).
Thanks for your reply.
Image
<table id="consignments-list" align="center" style="text-align: center; border-collapse: collapse;
border-spacing: 0;
width: 97%;
border: 3px solid #ddd;" cellpadding="10">
<thead>
<tr>
<th width="20%">ID</th>
<th width="40%">Name</th>
<th width="40%">Status</th>
</tr>
</thead>
<tbody>
<!-- load users here -->
</tbody>
</table>
<script id="jsbin-javascript">
window.onload = () => {
const table = document.querySelector('#consignments-list');
// call API using `fetch`
fetch('https://api.ulozenka.cz/v3/consignments', {
headers: new Headers({
'X-Shop': '18157',
'X-Key': '##################'
})
})
.then(res => res.json())
.then(res => {
// loop over all users
res.data.map(consignment => {
// create a `tr` element
const tr = document.createElement('tr');
// create ID `td`
const idTd = document.createElement('td');
idTd.textContent = consignment.id;
// create Name `td`
const statusTd = document.createElement('td');
statusTd.textContent = `${consignment.status.name}`;
//---
const nameTd = document.createElement('td');
nameTd.textContent = `${consignment.customer_name} ${consignment.customer_surname}`;
// add tds to tr
tr.appendChild(idTd);
tr.appendChild(nameTd);
tr.appendChild(statusTd);
// app tr to table
table.querySelector('tbody').appendChild(tr);
});
})
.catch(err => console.log('Error:', err));
};
</script>
If I understand you question correctly, what you want is create a onclick attribute into all td's elements. You can do something like this:
nameTd.setAttribute("onclick",`https://api.ulozenka.cz/v3/consignments/${consignment.id}`)
Related
I have a table generated with data from an array (the array contains more info than what is displayed in the table). I want to click on a row to see all info from the element.
Earlier done it like this:
let rows = document.getElementsByTagName("tr");
for (let row of rows) {
row.onclick = function rowClicked(evt) {
selected = myArray[evt.target.parentElement.rowIndex];
//code (not relevant)
}
But since I added a search feature myArray[1] is not necessarily equal to row number 1 and this method doesn't work.
Is it another way to find the element in the array from clicking on a random row?
The table is generated like this:
function drawTable(data) {
let table = document.getElementById("table");
table.innerHTML = "";
let tableHead = document.createElement("thead");
let colHeads = ["Names"];
for (let header of colHeads) {
let cell = document.createElement("th")
cell.innerHTML = header;
tableHead.appendChild(cell);
}
table.appendChild(tableHead)
for (var i = 0; i < data.length; i++){
let row = document.createElement("tr");
let name = document.createElement("td");
name.innerHTML = data[i].name.first + " " + data[i].name.last;
row.appendChild(name);
table.appendChild(row);
}
}
Any help is greatly appreciated!
You need some way to map a table row to its relevant entry in myArray which isn't dependent on the position of the row in the table. Data attributes wouldn't be affected.
Create a data-index attribute on each table row. Then, when it's clicked use the value of the data-index attribute to access the relevant myArray entry.
A simple version of what you have in mind. The visible line is bound with a click event. As soon as it is triggered, it gets the ref-id from the clicked element and toggles the reference column.
const clickables = document.querySelectorAll('.clickable');
console.log(clickables)
clickables.forEach(tr => {
tr.addEventListener('click', (e) => {
const ref = e.target.parentElement.getAttribute('data-ref');
const row = document.querySelector('#' + ref);
row.classList.toggle('hide');
});
});
td {
text-align: center;
padding: 20px;
}
.hide {
display: none;
}
.clickable {
cursor: pointer;
}
.clickable:hover {
background: #ccc;
}
<table border="1">
<tr class="clickable" data-ref="a">
<td>1</td>
<td>2</td>
</tr>
<tr id="a" class="hide">
<td>a1</td>
<td>b2</td>
</tr>
<tr class="clickable" data-ref="b">
<td>3</td>
<td>4</td>
</tr>
<tr id="b" class="hide">
<td>a3</td>
<td>a4</td>
</tr>
</table>
I want to make a row in a table selectable, however whenever I click the row, the console log shows that it did the right thing, but didn't change its class. Why is that and how can I fix it?
Part of the Code, that generates the select feature:
var tableconn = document.getElementById("connectionsLane"+laneid);
let row = tableconn.insertRow();
row.id = "row"+insertData.id;
row.onclick = function() {
if (row.classList.contains("selected")) {
console.log("unselected");
row.classList.remove("selected");
} else {
console.log("selected")
document.getElementById("row" + insertData.id).classList.add("selected");
}
}
insertData.id gets increased by 1 each time the whole thing is called, whilst laneid is dependent on which part of the website the user is currently refering to (is a int 1-255)
Here is a simple example of how you can select a table row and style it using a function. This function can be used for setting class name on rows in any table in a document.
// for setting the class name on a row in a table
const onrowselect = e => {
let table = e.target.closest('table');
let trs = table.querySelectorAll('tr');
// remove all class=selected
trs.forEach(tr => tr.classList.remove('selected'));
// the current tr
var tr = e.target.closest('tr');
tr.classList.add('selected');
};
// define a table
var table01 = document.getElementById('table01');
// add and eventlistener to the table
table01.addEventListener('click', onrowselect);
tr {
cursor: pointer;
}
.selected {
background-color: silver;
}
<table id="table01">
<tr>
<td>Row</td>
<td>1</td>
</tr>
<tr>
<td>Row</td>
<td>2</td>
</tr>
<tr>
<td>Row</td>
<td>3</td>
</tr>
</table>
so im trying to add a buttons to the end of each row since the table is dynamic I have to use javascript to append it but everytime I try it doesn't work if it does it will just put a button at the end of the last row of the table. Heres an image of what I get linked below
enter image description here
<!--TABLE HEADER SECTION-->
<div class="div0">
<table class="tableHeader">
<thead>
<tr>
<th>Store</th>
<th>Product</th>
<th>Profile</th>
<th>Proxies</th>
<th>Status</th>
<th>ACTION</th>
</tr>
</thead>
</table>
</div>
<!--TABLE SECTION-->
<div class="div1">
<table id = "botTasksTable" class="table table-dark table-sm table-bordered">
<tbody>
<tr>
<td>another name</td>
<td>mockdata</td>
<td>mockdata</td>
<td>mockdata</td>
<td>mockdata</td>
</tr>
</tbody>
</table>
</div>
<script type="text/javascript">
const tableBody = document.querySelector("#botTasksTable > tbody");
//function to load table into tbody from jsonfile bottable which would be the users given tasks
function loadBotTasksTable() {
const request = new XMLHttpRequest();
request.open("get", "data/botTable.json"); //grabs the data from the json file its in the data file/ and named bottable.json
request.onload = () => {
const json = JSON.parse(request.responseText); //attempts to parse the data it gets
populateTable(json);
};
request.send(); //sends out the request for thr function
}
var btn = document.createElement("BUTTON");
var btn = document.createElement("BUTTON"); // Create a <button> element
btn.innerHTML = "CLICK ME"; // Insert text
function populateTable(json) {
//this while loop clears out existing table data!
//we want to add this back but adding a value to first child even if its a mock value.
while (tableBody.firstChild) { //so basically checking if the table has <tr> <td></td> </tr> so a row and column
tableBody.removeChild(tableBody.firstChild)
}
//now we populate table
json.forEach((row) => { //loops through each row [ SUPREME, Nike SB Dunks, profile1, proxy22, In Progress ]
const tr = document.createElement("tr"); //create the new row
row.forEach((cell) => { //loops through each individual column of the row EX : SUPREME
const td = document.createElement("td");
td.textContent = cell // passes whatever data the json file had in the cell into the text content of the row
tr.appendChild(td);
});
//for each cell in the row get the index and append
tableBody.appendChild(tr); //appends the row into the table body row by row as i runs through the for loop
});
loopTable();
}
//loop through table and add button to the table
function loopTable() {
var table = document.getElementById('botTasksTable');
for (var i = 0, row; row = table.rows[i]; i++) {
//iterate through rows
//rows would be accessed using the "row" variable assigned in the for loop
row.appendChild(btn);
console.log(i);
}
};
You need to create a new button for each row, and put it inside a <td>. You can use cloneNode() to make a copy of an element.
//loop through table and add button to the table
function loopTable() {
var table = document.getElementById('botTasksTable');
for (var i = 0, row; row = table.rows[i]; i++) {
let td = document.createElement('td');
td.appendChild(btn.cloneNode());
row.appendChild(td);
console.log(i);
}
};
I am having a problem when I try to update the DOM with new information coming from an API.
Every time that I click to add new users, the array displays the old, and new information. Ideally, it would update the array first and then display only the new information. I will attach a picture of what is happening. I would like to every time the user click on add new user, the DOM update with only the information of that new user.
HTML part
<table class="table is-fullwidth table is-hoverable table-info">
<thead>
<tr">
<th title="Channel Name" class="has-text-left"> Channel Name </th>
<th title="View per week" class="has-text-right"> View per week </th>
</tr>
</thead>
<tbody id="body-table">
<tr id="tr-table">
</tr>
</tbody>
</table>
script.js
const trline = document.getElementById('body-table')
let usersList = [];
async function getnewUsers(){
const res = await fetch('https://randomuser.me/api')
const data = await res.json()
// create an instance of the results
const user = data.results[0]
// create the new user
const newUser = {
name:`${user.name.first} ${user.name.last}`,
social: Math.floor(Math.random() * 10000 )
}
// update the new user to the database...
addData(newUser)
}
function addData(obj) {
usersList.push(obj)
// update the information on the screen
updateDOM()
}
function updateDOM( providedData = usersList){
providedData.forEach(item => {
const element = document.createElement('tr')
element.innerHTML = `
<td class="has-text-left cname"> ${item.name} </td>
<td class="has-text-right cview"> ${item.social} k</td>
`
trline.appendChild(element)
})
}
addUser.addEventListener('click', getnewUsers)
Result picture:
I found the problem and the solution.
I didn't reset the HTML part to clear before adding a new item. I had to fix the function updateDOM with this: trline.innerHTML = ''
After that, the function works fine.
function updateDOM( providedData = usersList){
trline.innerHTML = '' // clear everything before adding new stuff
providedData.forEach(item => {
const element = document.createElement('tr')
element.innerHTML = `
<td class="has-text-left cname"> ${item.name} </td>
<td class="has-text-right cview"> ${item.social} k</td>
`
trline.appendChild(element)
})
}
I created a code to convert json data to html table using javascript and ajax:
(column 1 is text, column 2 is link, column 4 is image link)
Data:
[
["Product_1_Title", "www.website1.com", 20, "https://images-na.ssl-images-amazon.com/images/I/81b1roZwACL._AC_SL1500_.jpg"],
["Product_2_Title", "www.website2.com", 50, "https://images-na.ssl-images-amazon.com/images/I/71W1KvLH3sL._AC_SL1500_.jpg"],
...
]
This is the code, it work well, but on the table result, I want to hide column 2 and put the link in column 2 in an anchor in column 1 so the Title become clickable link, and put the image link on column 4 into src so the picture shown on the cell.
<body>
<table id="tab">
<thead>
<tr>
<th>column_1</th>
<th>column_2_link</th>
<th>column_3</th>
<th>column_4_link</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script type="text/javascript">
const TabBody = document.querySelector("#tab > tbody")
function loadData() {
const request = new XMLHttpRequest();
request.open("get", "rows.json");
request.onload = () => {
try {
const json = JSON.parse(request.responseText);
populateTable(json);
} catch (e) {
console.warn("error");
}
};
request.send();
}
function populateTable(json){
while(TabBody.firstChild){TabBody.removeChild(TabBody.firstChild);}
json.forEach((row) => {
const tr = document.createElement("tr");
row.forEach((cell) => {
const td = document.createElement("td");
// I tried this and it put the link text inside <a>
// td.innerHTML = /.com\//g.test(cell)
// ? `${cell}`
// : cell;
// and tried this and it put the link text inside <img>
td.innerHTML = /alicdn.com/g.test(cell)
? `<img src="https://${cell}" class="img-fluid"/>`
: cell;
tr.appendChild(td);})
TabBody.appendChild(tr);
})
}
document.addEventListener("DOMContentLoaded", () => { loadData();})
</script>
</body>
Instead of iterating through the cells, if you know the position of the columns in the array you can hard code the row.
function populateTable(json){
while(TabBody.firstChild){TabBody.removeChild(TabBody.firstChild);}
json.forEach((row) => {
const tr = document.createElement("tr");
let td = document.createElement("td");
td.innerHTML = `<a href='${row[1]}'>${row[0]}</a>`
tr.appendChild(td);
td = document.createElement("td");
td.innerHTML = row[2];
tr.appendChild(td);
td = document.createElement("td");
td.innerHTML = `<img src="https://${row[3]}" class="img-fluid"/>`;
tr.appendChild(td);
TabBody.appendChild(tr);
})
}
And take out the second column in the table instead of hiding it
<thead>
<tr>
<th>column_1</th>
<th>column_2</th>
<th>column_3_link</th>
</tr>
</thead>