Get the id of object in a tablerow - javascript - javascript

Hey i'm trying to get the id of the specific object so that i can send it to the backend for now. I'm having a hard time get the individual object and not the whole list at once.
If anything looks funky it's because I'm pretty new at this and it's been alot of trial and error
my javascript looks like this:
//waits for the html doc to be ready before atempting to run any js.
$(document).ready( () =>{
// jquery getting our json order data from API
$.get("http://localhost:8888/orderslist", (data) => {
// loops through our orderlist api
let rows = data.map(item => {
let $clone = $('#frontpage_new_ordertable tfoot tr').clone();
$clone.find('.customer_name').text(item.customer_name);
$clone.find('.date').text(item.date);
$clone.find('.time').text(item.time);
$clone.find('.pickup').text(item.pickup);
$clone.find('.comments').text(item.comments);
$clone.find('.total').text(item.total + ' Kr.');
let foo = function(){
//gets id from object and sends it to backend using get method
};
// accept and cancel buttons
$clone.find('.order_status').html(
`<button id = "acceptOrder" type="button" onclick="${foo()}">Accept</button>` +
`<button id = "cancelOrder" type="button" onclick="${foo()})">Cancel</button>`
);
// loops through orders product name
let productsName = item.products.map(prod => `${prod.name}`);
$clone.find('.products').html(productsName.join('<br />'));
// loops through orders product price
let productsPrice = item.products.map(prod => `${prod.price} Kr.`);
$clone.find('.price').html(productsPrice.join('<br />'));
return $clone;
});
//appends to our frontpage html
$("#frontpage_new_ordertable tbody").append(rows);
});
});
This is the json data i get from my route.
{
id: "3JBBdJdBUP7QyDvCnmsF",
date: "30/04-2020",
time: "13:40:41",
total: 40,
products: [
{
name: "Caffe Latte",
price: 40
}
]
}
My html looks like this:
<!-- this is the table of new orders -->
<table id="frontpage_new_ordertable">
<tbody>
<tr>
<th>Customer</th>
<th>Date</th>
<th>Ordered at</th>
<th>Wished pickup time</th>
<th>Order</th>
<th>Comments</th>
<th>Price</th>
<th>Total</th>
<th>Order Status</th>
</tr>
</tbody>
<tfoot>
<tr>
<td class="customer_name"></td>
<td class="date"></td>
<td class="time"></td>
<td class="pickup"></td>
<td class="products"></td>
<td class="comments"></td>
<td class="price"></td>
<td class="total"></td>
<td class="order_status"></td>
</tr>
</tfoot>
</table>
After edit it looks like this. I'm not seeing the accept button
// loops through our orderlist api
let rows = data.map(item => {
let $clone = $('#frontpage_new_ordertable tfoot tr').clone();
$clone.data("id", item.id);
$clone.find('.date').text(item.date);
$clone.find('.time').text(item.time);
$clone.find('.pickup').text(item.pickup);
$clone.find('.comments').text(item.comments);
$clone.find('.total').text(item.total + ' Kr.');
$(function() {$(document).on("click", ".acceptOrder", foo);
function foo() {
var btn = $(this);
var row = btn.closest("tr");
var id = row.data("id");
var name = row.find(".customer_name").text();
};
$clone.find('.order_status').html(
`<button type="button" class='acceptOrder">Accept</button>`
);
});

The relevant parts of the code are:
$(function() {
$.get("http://localhost:8888/orderslist", (data) => {
// loops through our orderlist api
let rows = data.map(item => {
let $clone = $('#frontpage_new_ordertable tfoot tr').clone();
let foo = function(){
//gets id from object and sends it to backend using get method
};
$clone.find('.order_status').html(
`<button id="acceptOrder" type="button" onclick="${foo()}">Accept</button>`
);
return $clone;
});
//appends to our frontpage html
$("#frontpage_new_ordertable tbody").append(rows);
});
});
First step is to remove the duplicate id: and onclick=
$(function() {
$(document).on("click", ".acceptOrder", foo);
function foo() {
}
...
$clone.find('.order_status').html(
`<button type="button" class='acceptOrder">Accept</button>`
);
...
});
Now, clicking the Accept button will call 'foo' as an event, with this as the button. You can get the original JSON ID by either putting this on the button as a data-id or on the parent tr:
let rows = data.map(item => {
let $clone = $('#frontpage_new_ordertable tfoot tr').clone();
$clone.data("id", item.id);
then, in foo, you can get this as:
function foo() {
var btn = $(this);
var row = btn.closest("tr");
var id = row.data("id");
var name = row.find(".customer_name").text();
...
}
the alternative is to add to the button in the same way - I tend to use it on the tr as you'll probably need to get the tr anyway and it means it's available from any element (eg another button).
`<button type="button" data-id="${item.id}" ...
To include some more context:
$(document).ready(() =>{
// add event listener here
$(document).on("click", ".acceptOrder", foo);
// add the event handler at the top-level inside doc.ready
function foo() {
var btn = $(this);
var row = btn.closest("tr");
var id = row.data("id");
var name = row.find(".customer_name").text();
...
}
// original code
$.get("http://localhost:8888/orderslist", (data) => {
// loops through our orderlist api
let rows = data.map(item => {
let $clone = $('#frontpage_new_ordertable tfoot tr').clone();
// add ID to the row as a data-id
$clone.data("id", item.id);
// original code
$clone.find('.customer_name').text(item.customer_name);
...etc
// remove let foo =
// let foo = function(){
// update accept/cancel buttons
// accept and cancel buttons
$clone.find('.order_status').html(
`<button class="acceptOrder" type="button">Accept</button>` +
`<button class="cancelOrder" type="button">Cancel</button>`
);

Related

how to create new td's from user input dynamically

I am trying to make a data table from user input. i found out this solution that i am making objects from user input and pushing them to an array. after that, I am doing a for loop to make td. but somehow those datas are re writing in the same raw. and previous raw datas are getiing replaced by new input datas.what I am doing wrong here and every time I am refreshing the page the array is getting empty how to prevent this help me out tnx.
const form = document.getElementById("form");
const tdbody = document.getElementById("data");
const carDatas = [];
let count = 0;
class Car {
constructor(plate, carMaker, carModel, carOwner, carPrice, carColor) {
(this.plate = plate),
(this.carMaker = carMaker),
(this.carModel = carModel),
(this.carOwner = carOwner),
(this.carPrice = carPrice),
(this.carColor = carColor);
}
}
form.addEventListener("submit", (e) => {
const plate = document.getElementById("plate").value;
const carMaker = document.getElementById("carMaker").value;
const carModel = document.getElementById("carModel").value;
const carOwner = document.getElementById("carOwner").value;
const carPrice = document.getElementById("carPrice").value;
const carColor = document.getElementById("carColor").value;
const carDetails = new Car(
plate,
carMaker,
carModel,
carOwner,
carPrice,
carColor
);
carDatas.push(carDetails);
for (let i = 0; i < carDatas.length; i++) {
document.getElementById("data").innerHTML = document.createElement(
"tr"
).innerHTML = `<td>${carDatas[i].plate} </td>
<td>${carDatas[i].carMaker} </td>
<td>${carDatas[i].carModel} </td>
<td>${carDatas[i].carOwner} </td>
<td>${carDatas[i].carPrice} </td>
<td>${carDatas[i].carColor} </td> `;
}
e.preventDefault();
});
here is my html for table
<div class="database">
<h1>Cars Database</h1>
<table>
<thead>
<tr>
<th>LICENCE</th>
<th>MAKER</th>
<th>MODEL</th>
<th>OWNER</th>
<th>PRICE</th>
<th>COLOR</th>
</tr>
</thead>
<tbody id="data"></tbody>
</table>
</div>
Your for loop is bad!
I don't know if this part of your code is working, but if you have an array of objects you should see a function for arrays that is called map
arr.map((object) => {
return <td>{object.plate}</td>
})
this function is example, try to look for documentation

How to create reordering functionality for rows in a table using JavaScript

I'm currently refactoring a project that is using Python widgets along with JavaScript. It currently uses a table with a reorder feature that could use some major improvements. When using the "reorderRowDown" button, it works correctly the current row moves down and the previous and next row adjust accordingly.
However, on the "reorderRowUp" button the current row simply alternates back and forth between the current and previous row. (I hope I'm explaining this well, my apologies) It's very clunky moving the current row up the table.
I would like to achieve the functionality similar to "reorderRowDown" where when clicking "reorderRowUp" the current row moves up and the previous and next row adjust accordingly. In summary, I would like to know how to implement reordering of the rows in the table either up or down the correct way. Any help would be greatly appreciated.
(Here are gifs posted below to better demonstrate the scenarios I'm referencing)
reorderRowDown Example:
https://media.giphy.com/media/8WHiGw57pPTK9Zdibk/giphy.gif
reorderRowUp Example:
https://media.giphy.com/media/Wp7x9GtYDX29cFLT6I/giphy.gif
Here's my code (please let me know if you require more)
PathContext.js
'use strict';
module.exports = () => {
window.reorderRowUp = function(ruleSetIdPriority) {
let ruleSetId;
ruleSetId = ruleSetIdPriority.split('-priority')[0];
const row = document.getElementById(ruleSetId);
const table = row.parentNode;
const prevRow = row.previousElementSibling;
table.insertBefore(row, prevRow);
};
window.reorderRowDown = function(ruleSetIdPriority) {
let ruleSetId;
ruleSetId = ruleSetIdPriority.split('-priority')[0];
const row = document.getElementById(ruleSetId);
const table = row.parentNode;
const nextRow = row.nextElementSibling;
table.insertBefore(nextRow, row);
};
};
reorder_row_widget.html
<button class="reorder-btn" type="button" onclick=reorderRowUp("{{widget.name}}")>Up</button>
<button class="reorder-btn" type="button" onclick=reorderRowDown("{{widget.name}}")>Down</button>
<input id="{{ widget.name }}" type="hidden" name="{{ widget.name }}" value="{{ widget.value }}"></input>
Here's the html of the actual table row from the console in my browser
<table>
<tbody>
<tr class="form-row row1 has_original dynamic-rule_set" id="rule_set-0">
<td class="original">
<p>
Rule object (84)
</p>
<input type="hidden" name="rule_set-0-id" value="84" id="id_rule_set-0-id">
<input type="hidden" name="rule_set-0-path_context" value="6" id="id_rule_set-0-path_context">
</td>
<td class="field-priority">
<button class="reorder-btn" type="button" onclick="reorderRowUp("rule_set-0-priority")">Up</button>
<button class="reorder-btn" type="button" onclick="reorderRowDown("rule_set-0-priority")">Down</button>
<input id="rule_set-0-priority" type="hidden" name="rule_set-0-priority" value="-301">
</td>
<td class="field-pattern">
<input type="text" name="rule_set-0-pattern" value="^/$" id="id_rule_set-0-pattern">
</td>
<td class="field-value">
<input class="tgl" id="rule_set-0-value" name="rule_set-0-value" type="checkbox" checked="">
<label class="tgl-btn" for="rule_set-0-value"></label>
</td>
<td class="field-experience">
<select name="rule_set-0-experience" id="id_rule_set-0-experience">
<option value="">---------</option>
<option value="modal" selected="">Modal</option>
<option value="sticky_cta">Sticky CTA</option>
</select>
</td>
<td class="delete"><input type="checkbox" name="rule_set-0-DELETE" id="id_rule_set-0-DELETE"></td>
</tr>
</tbody>
</table>
admin.py (python code if needed)
class ReorderRowWidget(forms.Widget):
template_name = 'admin/reorder_row_widget.html'
def get_context(self, name, value, attrs=None):
return {'widget': {
'name': name,
'value': value,
}}
def render(self, name, value, attrs=None, renderer=None):
context = self.get_context(name, value, attrs)
template = loader.get_template(self.template_name).render(context)
return mark_safe(template)
Here is the implementation I used to resolve my issue and create a better UI. I refactored the PathContext.js file.
function replaceReorderFunction() {
const reorderRowUp = window.reorderRowUp || function() {};
const reorderRowDown = window.reorderRowDown || function() {};
// when page gets rendered, django creates a hidden row with a special ruleSetId with id __prefix__
// once 'add new row' is clicked, a real ruleSetId is given to the row
// need to replace the reorder function of that row so that it uses the proper ruleSetId so the row can be reordered properly
// should only need to happen once, on the first reordering after the row is added
// therefore I assume that the row in question is always at the bottom of the table
const tableWrapper = document.getElementById('rule_set-group');
const tbody = tableWrapper.querySelector('tbody');
const rowToUpdate = tbody.lastElementChild.previousElementSibling.previousElementSibling;
const priorityField = rowToUpdate.getElementsByClassName('field-priority')[0];
const buttons = priorityField.getElementsByTagName('button');
buttons[0].onclick = () => {reorderRowUp(rowToUpdate.id);};
buttons[1].onclick = () => {reorderRowDown(rowToUpdate.id);};
return rowToUpdate.id;
}
window.reorderRowUp = function(ruleSetIdPriority) {
let ruleSetId;
// it's a new row, ruleSetId is not correct
if (ruleSetIdPriority.match(/__prefix__/)) {
// get the proper ruleSetId and replace existing onclick functions
ruleSetId = replaceReorderFunction();
} else {
ruleSetId = ruleSetIdPriority.split('-priority')[0];
}
const row = document.getElementById(ruleSetId);
const table = row.parentNode;
const prevRow = row.previousElementSibling;
if (!prevRow) {
return;
}
table.insertBefore(row, prevRow);
// swap priority values
const prevPriorityValue = getPriorityValueFromRow(prevRow);
const curPriorityValue = getPriorityValueFromRow(row);
setPriorityValueOfRow(row, prevPriorityValue);
setPriorityValueOfRow(prevRow, curPriorityValue);
};
window.reorderRowDown = function(ruleSetIdPriority) {
let ruleSetId;
// it's a new row, ruleSetId is not correct
if (ruleSetIdPriority.match(/__prefix__/)) {
ruleSetId = replaceReorderFunction();
} else {
ruleSetId = ruleSetIdPriority.split('-priority')[0];
}
const row = document.getElementById(ruleSetId);
const table = row.parentNode;
const nextRow = row.nextElementSibling;
if (!nextRow || nextRow.className === 'add-row' || nextRow.id.includes('empty')) {
return;
}
table.insertBefore(nextRow, row);
// swap priority values
const nextPriorityValue = getPriorityValueFromRow(nextRow);
const curPriorityValue = getPriorityValueFromRow(row);
setPriorityValueOfRow(row, nextPriorityValue);
setPriorityValueOfRow(nextRow, curPriorityValue);
};

Using local storage to add user inputted rows permanently on HTML

I am creating a website that takes two inputs a topic and a link and it appends them as a row to the HTML table. On clicking a '+' button it must do the needful. I wanted to use local storage so as to store these links and topics on the page permanently. Since I am new to the concept on local storage, any type of help would be appreciated.
This is my code snippet:
let table = document.querySelector('table');
let topicInput = document.querySelector('#topic');
let linkInput = document.querySelector('#link');
function getTopic () {
return localStorage.getItem("mytopic");
}
function getLink () {
return localStorage.getItem("mylink");
}
function updatePage () {
let topic = topicInput.value;
let link = linkInput.value;
let template = `
<tr>
<td>${topic}</td>
<td>${link}</td>
<td><input type="button" id="buttonDelete" value="-" onclick="deleteRow(this)"></td>
</tr>`;
table.innerHTML += template;
}
function addFunction () {
var rTopic = document.getElementbyId("topic").value;
var rLink = document.getElementbyId("link").value;
localStorage.setItem("mytopic", rTopic);
localStorage.setItem("mylink", rLink);
updatePage();
};
<input type="text" id="topic" placeholder="Add topic" size="50">
<input type="text" id="link" placeholder="Add link" size="50">
<button id="buttonAdd" onclick="addFunction()">+</button>
The basic idea is you would need to store a stringified array into local storage and parse it back out when the page loads. You append to the array when you add new rows.
const table = document.querySelector('table tbody');
const topicInput = document.querySelector('#topic');
const linkInput = document.querySelector('#link');
// grab the records from local storage.
const records = JSON.parse(localStorage.getItem("data") || '[]');
const rowIndex = 0;
function addRecord(topic, link) {
const template = `
<tr>
<td>${topic}</td>
<td>${link}</td>
<td><input type="button" class="buttonDelete" value="-"></td>
</tr>`;
table.innerHTML += template;
}
function addFunction() {
const rTopic = document.getElementById("topic").value;
const rLink = document.getElementById("link").value;
// add to the array
records.push({
topic: rTopic,
link: rLink
});
updateLocalStorage();
addRecord(rTopic, rLink);
};
function updateLocalStorage() {
// save updated records array
localStorage.setItem("data", JSON.stringify(records));
}
table.addEventListener("click", function (evt) {
const delButton = evt.target.closest(".buttonDelete");
if (delButton) {
const row = delButton.closest("tr");
const index = Array.from(row.parentNode.children).indexOf(row);
records.splice(index, 1);
row.remove();
updateLocalStorage();
}
})
// loop over the records in localstorage.
records.forEach(function(record) {
addRecord(record.topic, record.link);
});
<input type="text" id="topic" placeholder="Add topic" size="50">
<input type="text" id="link" placeholder="Add link" size="50">
<button id="buttonAdd" onclick="addFunction()">+</button>
<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
</tr>
</thead>
<tbody></tbody>
</table>
And as I stated before, localstorage is not permanent. It can be easily cleared and it is also limited to the amount of data it can store.

How to multiply 2 td in Javascript?

I have a table where one td gets 1 if a checkbox is checked and I would like to multiple this td with another and display it in a third one.
See the html here:
<div>
<input type="checkbox" id="fut1">check</input>
</div>
<table border="1" cellpadding="10" id="countit">
<tr>
<td id="td1"></td>
<td id="td2">5000</td>
<td id="td3"></td>
</tr>
</table>
And here is the js:
$('#fut1').change(function () {
if ($(this).is(":checked")) {
$('#td1').text('1');
} else {
$('#td1').text('0');
}
});
$('#td1').change(function () {
var me = $('#td1').value;
var ar = $('#td2').value;
var sum = me * ar;
$('#td3').text(sum);
});
$('#td1').change(function () { // <--- td elements don't have a change event listener/handler
var me = $('#td1').value; // <--- td elements don't have a value
var ar = $('#td2').value; // <--- td elements don't have a value
var sum = me * ar;
$('#td3').text(sum);
});
If you want to do it this way:
$('#fut1').change(function () {
if ($(this).is(":checked")) {
$('#td1').text('1');
} else {
$('#td1').text('0');
}
callTdChange();
});
function callTdChange() {
var me = parseInt($('#td1').text());
var ar = parseInt($('#td2').text());
var sum = me * ar;
$('#td3').text(sum);
}
Of course, the better way should be to use form elements (inputs) in the case you want to save your data to a server, or use change behaviors.
#td1 doesn't support the change event, because that's only meant for interactive elements (like input, select, or textarea).
You can either do the calculation in your first event listener in #fut1, or declare an input element inside #td1.

jQuery - get next element inside checkbox each

I have a table with following columns: checkbox, text, text, ...
For every selected checkbox I need to get the 2nd text value and test if contains some value.
My code so far
$('input:checkbox').each(function () {
var current = $(this);
if (current.is(':checked')) {
var txt = current.next('.inf-name').text();
if (txt.contains(inf) { ... }
}
});
razor code:
<table class="table table-bordered table-modified">
<thead>
<tr>
<th></th>
<th>State</th>
<th>Lookup Type</th>
<th>Plates</th>
<th>Notices</th>
</tr>
</thead>
<tbody>
#Html.HiddenFor(p => p.OrgUnitID, new { #Value = orgUnitId })
#for(var ind = 0; ind < records.Count(); ++ind)
{
var r = records[ind];
var i = ind;
#Html.HiddenFor(p => p.Comp[i].State, new { #Value = #r.State })
<tr>
<td>#Html.CheckBoxFor(p => p.Comp[i].Checked)</td>
<td>#r.State</td>
#if (dict.ContainsKey(r.State))
{ <td class="inf-name">#dict[r.State].ToString()</td> }
else
{ <td class="inf-name"></td> }
<td>#Html.ActionLink(#r.Plates.ToString(CultureInfo.InvariantCulture), "Plates", new { controller = "Lookup", state = #r.State})</td>
<td>#Html.ActionLink(#r.Notices.ToString(CultureInfo.InvariantCulture), "Plates", new { controller = "Lookup" }, new { state = #r.State })</td>
</tr>
}
</tbody>
</table>
where inf-name is the class on 2nd element. I can't get it done. Anyone know a solution?
using next() will get the direct sibling , you need to get parent for check box which is a <td> find the next next sibling using nextAll().eq(1) , get the text inside the that sibling using .text()
Edit :
if you want your target using classes ( provided classes will never change later ) , then just change your code to be :
$('input:checkbox').each(function () {
var current = $(this);
if (current.is(':checked')) {
var txt = current.next('.inf-name').eq(1).text();
if (txt.contains(inf) { ... }
}
});
var currentRows = $('.table tbody tr');
$.each(currentRows, function () {
$(this).find(':checkbox').each(function () {
if ($(this).is(':checked')) {
console.log($(currentRows).eq(1).val());
}
});
});

Categories

Resources