How to make DataTable, but the row is only appended - javascript

I have a table that add rows manually, but I want to make it into a DataTable to make it friendly user. But I don't know how to do it.
I tried to search it online and I see this, it is similar but it is not working or I'm doing something wrong... See here
Also this is my code :
const tbody = document.getElementById("choicesListTbodyADD");
const btnAdd = document.querySelector("button");
const inputChoices = document.querySelector("input");
var count = 1;
btnAdd.addEventListener("click", function () {
$(tbody).append(`<tr><td>${count}</td><td>${inputChoices.value.trim()}</td><td>DELETE</td></tr>`)
inputChoices.value = '';
})
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<br><br>
<input type="text" id="choices"/>
<button id="appendChoices">Add Choices</button>
<br><br>
<table class="table text-center table-bordered table-striped dataTable dtr-inline" id="ADDchoicesARTableListSequence">
<tr>
<th>No.</th>
<th>Choices</th>
<th>Action</th>
</tr>
<tbody id="choicesListTbodyADD"></tbody>
</table>

Here is an approach, based on your non-DataTables code.
I have included the Bootstrap libraries I think you need - but you can adjust those if needed.
$(document).ready(function() {
var table = $('#ADDchoicesARTableListSequence').DataTable();
const tbody = document.getElementById("choicesListTbodyADD");
const btnAdd = document.querySelector("button");
const inputChoices = document.querySelector("input");
var count = 1;
btnAdd.addEventListener("click", function() {
table.row.add($(`<tr><td>${count}</td><td>${inputChoices.value.trim()}</td><td>DELETE</td></tr>`)).draw();
count += 1;
inputChoices.value = '';
})
});
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo</title>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.3/css/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.1/css/dataTables.bootstrap5.css" />
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.3/js/bootstrap.bundle.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.13.1/js/jquery.dataTables.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.13.1/js/dataTables.bootstrap5.js"></script>
</head>
<body>
<div style="margin: 20px;">
<input type="text" id="choices" />
<button id="appendChoices">Add Choices</button>
<br><br>
<table class="table text-center table-bordered table-striped dataTable dtr-inline" id="ADDchoicesARTableListSequence">
<thead>
<tr>
<th>No.</th>
<th>Choices</th>
<th>Action</th>
</tr>
</thead>
</table>
</div>
</body>
</html>
The main points to note:
Your HTML table does not need a <body> in this case, as DataTables will provide it for you.
Don't forget to use draw() after adding each row - to re-draw the table, so the new data is displayed.
In this case, I create a new DOM node from your data using $(<tr>...</tr>). But you can see from the documentation that there are other ways you can create new rows:
using an array
using an object
using a node (which is what we do here)
I chose to use a node because that is the closest to what your code already does.

Related

How do I make DeferRender work for datatables on a page? (Client-Side Processing)

I'm trying to use deferRender for my datatables to limit the number of values that first show up. But it does not appear to be making any difference.
The data I am working with has thousands of rows, and I need to use client-side processing (I'm hosting a static page on github pages). The problem I am facing is simply that there are too many values and my page is loading far too slowly.
It needs to still be responsive to several click/search events, so that when the user searches or clicks several filters, the datatable updates - but I would again prefer that it only shows the first page of results.
const url = 'https://raw.githubusercontent.com/________________.json';
async function populate() {
const response = await fetch(url);
const evidenceData = await response.json();
console.log(evidenceData)
// Build Table
function buildTable(data) {
var table = document.getElementById('myTable')
table.innerHTML = data.map(function(row) {
let [country, title, category, date, link, image] = row;
return `<tr>
<td>
<br><br>
<a href="${link}" target='_blank'>
<img class="tableThumbnail" src=${image}><br><br>
</td></a>
<td>
<span class="tableTitle"><br><br><a href="${link}" target='_blank'>${title}</a><br></span>
</td>
<td>${country}</td>
<td>${category}</td>
<td>${date}</td>
</tr>`;
}).join('');
}
$(document).ready(function() {
var oTable = $('.mydatatable').DataTable({
"dom": "<<t>ip>",
"columnDefs": [{
targets: [2, 3, 4],
visible: false,
searchable: true,
}]
});
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.14.7/dist/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.3.1/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<!-- Datatables -->
<link rel="stylesheet" href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css">
<script src="https://cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js"></script>
</head>
<body>
<form class="form">
<div>
<input type="text" id="searchInput" class="form-control" placeholder=" Search">
</div>
</form>
<div class="main">
<table class="table mydatatable" id="mydatatable">
<thead>
<tr>
<th> </th>
<th> </th>
<th> </th>
<th> </th>
</tr>
</thead>
<tbody id="myTable">
</tbody>
</table>
</div>
</body>

How to get element id using v-for vuejs directive?

I'm a vue.js beginner, so I need help.
I write an HTML page which show a list of object in a simple table.
The table is made by a script which get a JSON object from a servlet and shows it using a v-for directive.
In each row of the table, there is a button that the user can click to book the object wrote in the corresponding row, using a form.
The problem is that I don't know how to get the object's information correspondent to the clicked line to put it in the form's fields.
This is the code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Repetition - catalog</title>
<meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style2.css" />
</head>
<body>
<header><h1>REPETITIONS.com</h1></header>
<div id="app" class="float-container" style="height: 80%">
<table class="catalog-table">
<thead>
<tr>
<th style="width: 200px">Corso</th>
<th style="width: 250px">Docente</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="rep in reps">
<td>{{rep.teacherName}} {{rep.teacherSurName}}</td>
<td>{{rep.course}}</td>
<td>
<form action="/Repetition/controller/ServletController" method="post" id="i">
<input type="hidden" name="operation" value="booking">
<input type="hidden" name="id_t" value="rep.getId_teac"> <---set the value of the current row
<input type="hidden" name="id_c" value="rep.getId_cor"> <---set the value of the current row
<button type="submit">Book</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
<footer>xxxxxxx</footer>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
var app = new Vue ({
el: '#app',
data: {
repetitions: [],
link: '/Repetition/ServletController?operation=catalog&device=x'
},
mounted(){
this.getRepetitions()
},
methods:{
getRepetitions: function(){
var self = this;
$.get(this.link, function(data) {
self.repetitions = data;
});
}
}
});
</script>
</body>
</html>
Alternatively the form request could be manage with another script, but there would be the same problem.

using a forEach loop to build html table and date/time comes through as null

I am using Google Apps Script and Javascript to build a WebApp. Using a forEach loop to pull data from the GoogleSheet to build the HTML table I have a date time field as the 6th column in my table. When the table goes to populate there is an error -
Uncaught TypeError: Cannot read property 'forEach' of null -
If i drop the column from the function getTableData the html table will populate without the date time stamp. How do I get the date/time stamp to come through in the forEach loop?
document.addEventListener("DOMContentLoaded", function() {
//The google script ill call get table data passing data. on success it will call the generateTable passing the data from data array.
google.script.run.withSuccessHandler(generateTable).getTableData();
//note the above function getTableData is a function in the code.gs file see bottom of page for the contents of file
});
function generateTable(dataArray) {
var tbody = document.getElementById("table-body");
dataArray.forEach(function(r) {
var row = document.createElement("tr");
var col1= document.createElement("td");
col1.textContent = r[0];
var col2= document.createElement("td");
col2.textContent = r[1];
var col3= document.createElement("td");
col3.textContent = r[2];
var col4= document.createElement("td");
col4.textContent = r[3];
var col5= document.createElement("td");
col5.textContent = r[4];
var col6= document.createElement("td");
col6.textContent = r[5];
tbody.appendChild(col1);
tbody.appendChild(col2);
tbody.appendChild(col3);
tbody.appendChild(col4);
tbody.appendChild(col5);
tbody.appendChild(col6);
tbody.appendChild(row);
});
}
//code.gs function getTableData
function getTableData() {
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("Data");
// the 6 in the below variable is the 6th column in my googlesheet and is a data/time stamp. this is where I am throwing the error. if i change it to 5 it works, but does not get the date/time stamp on the html table
var data = ws.getRange(2,1, ws.getLastRow() -1, 6).getValues();
Logger.log("data : " + data);
return data;
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!--Bootstrap link -->
<!-- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> -->
<!--materialize link -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<?!= include("pageCSS"); ?>
</head>
<body>
<div class="container">
<div class="row">
<div class="input-field col s12">
<h1>Guest List Data Table</h1>
<table id="tableId1">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Cred Type</th>
<th>Zip Code</th>
<th>Estimate</th>
<th>Time</th> <!-- this is the column where D/T stamp should show -->
</tr>
</thead>
<tbody id="table-body">
</tbody>
</table>
</div>
</div>
<!-- CLOSE ROW -->
<div class="row">
<div class="col s12">
<table id="tableId" border=1>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Cred Type</th>
<th>Zip Code</th>
<th>Estimate</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<tr>
<td>DANIELLE</td>
<td></td>
</tr>
<tr>
<td>Item </td>
<td>two</td>
</tr>
<tr><td>Item three</td></tr>
</tbody>
</table>
</div>
</div>
<!-- CLOSE ROW -->
</div>
<!-- CLOSE CONTAINER -->
<!-- SCRIPT FOR MATERIALIZE -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<!-- SCRIPTS FOR BOOTSTRAP -->
<!-- <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script> -->
<?!= include("table-js"); ?>
</body>
<footer>
<div class="container">
<div class="row" align="center">
Back to Main Menu
</div>
</div>
</footer>
</html>
Date objects are illegal as parameters between server and client. Convert them to strings using JSON.stringify() or use getDisplayValues() instead of getValues()

Want to move an added element to a different part of the DOM

I'll try and state what im trying to do and hope it makes sense (i only learned this last week!). When clicking the delete button that i create, i would like the content associated along with it to go down into a panel body i created in my HTML page with a class name of 'panelAdd'. Any help is much appreciated as i am quite new. Thanks for reading. Ill put the HTML first
HTML
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootswatch/3.3.5/darkly/bootstrap.css" crossorigin="anonymous" />
<link rel="stylesheet" type="text/css" href="css/style.css" />
<title>To Do List</title>
</head>
<body>
<h3 class="header">
<strong>To Do List</strong>
</h3>
<table class="table table-responsive myTable col-xs-offset2" id="myTable">
<thead>
<th>Complete?</th>
<th>Task to Complete</th>
<th>Time to Complete?</th>
<th>Remove?</th>
</thead>
<tbody>
<tr>
</tr>
<tr>
<td><input type="checkbox" class="newCheck col-xs-offset-2" value=""></td>
<td><input type="text" class="newWord" placeholder="New task"></td>
<td><input type="text" class="newTime" placeholder="How long do you have?"></td>
<td><button class="btn btn-primary buttonAdd">Add Task</button></td>
</tr>
</tbody>
</table>
<footer>
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">Completed!</h3>
</div>
<div class="panel-body"></div>
</div>
</footer>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script type="text/javascript" src="js/add.js"></script>
<script type="text/javascript" src="js/remover.js"></script>
</body>
</html>
Add button
$(document).ready(function (){
$(".btn-primary").on("click", function(e) {
e.preventDefault();
var newWord, newRow, wordTd, newCheck, deleteButton, deleteTd;
var isDuplicate;
newWord = $(".newWord").val();
newTime = $(".newTime").val();
newCheck = $(".newCheck").val();
var newRow = $("<tr>");
var newCheck = $("<input>").attr("type", "checkbox").attr("class", "newCheck").attr("data-state", "not-checked");
var wordTd = $("<td>").append(newWord).before();
var timeTd = $("<td>").append(newTime).before();
var deleteButton = $("<button>").addClass("btn btn-danger buttonRemove").append("Remove");
var deleteTd = $("<td>").append(deleteButton);
newRow.append(newCheck).append(wordTd).append(timeTd).append(deleteTd).before();
$("tbody").append(newRow);
$("#newWord").val("")
});
});
$(document).on("click", ".newCheck", function(){
if($(this).prop("checked") === true){
$(this).parent().attr("class", "done");
}
else{
$(this).parent().removeClass();
}
});
Remove Button
$(document).ready(function (){
$(document).on("click",".btn-danger", function(){
$(this).parents("tr").remove();
});
});
FIDDLE
Remove Button
$(document).on("click",".btn-danger", function(){
$t = $(this).closest('tr').find('td')[0];
$(this).parents("tr").remove();
$('.panel-body').append($t);
});
});
What you can do is grab the content you want to insert and append it in the target panel in this case .panel-body. See the fiddle above which adds the task name to the Completed list.
Do you expect like this.
Fiddle Sample
Code snippets:
$(document).on("click",".btn-danger", function(){
var removed = $(this).parents("tr").remove();
$(".panel-body").append('<div class="panelAdd"></div>').append(removed);
});
Let me know if this helps!
DEMO
You can just use .detach and .appendTo on click event of your remove button as below:
$(document).on("click",".btn-danger", function(){
var detachedRow=$(this).parents("tr").detach(); //detach and store it as reference
detachedRow.find('input[type="checkbox"]').remove();
//I hope you don't need checkbox when task is complete so removing it from that row
detachedRow.appendTo($('.panel .panel-body #myTableCompleted tbody'));
append it to your completed panel
});
Note : The .detach() method is the same as .remove(), except that
.detach() keeps all jQuery data associated with the removed elements.
This method is useful when removed elements are to be reinserted into
the DOM at a later time.
I have also added the table structure in your .panel-body to get the same UI look and have removed column for checkbox from the same and it is as below:
<div class="panel-body">
<table class="table table-responsive myTable col-xs-offset2" id="myTableCompleted">
<thead>
<th>Task to Complete</th>
<th>Time to Complete?</th>
<th>Remove?</th>
</thead>
<tbody>
</tbody>
</table>
</div>
Note - I think there might be other requirements too like only checked
checkbox to be added to that completed panel-body etc., and if yes
there will be a minor change in the delete code

Getting total sum of rows and adding and removing rows using knockoutjs

I am fairly new to knockoutjs. I am creating a simple table and trying to sum up all the values in the "total" column. Plus, I am also implementing "Add column" and "Remove Column" functionalities using knockoutjs.
The problem is that both the Add and Remove funcitonalities and not working. Plus,the "TotalSurcharge" value is not displaying on the UI.
Here's my js:
// Class to represent a row in the table
function addMaterial() {
this.name = ko.observable("");
this.quantity = ko.observable("");
this.rate = ko.observable(0);
this.formattedTotal = ko.computed(function() {
return this.rate() * this.quantity();
}, this);
}
function documentViewModel(){
var self = this;
//create a mateirals array
self.materials = ko.observableArray([
new addMaterial()
]);
// Computed data
self.totalSurcharge = ko.computed(function() {
var total = 0;
for (var i = 0; i < self.materials().length; i++)
total += self.materials()[i].formattedTotal();
return total;
});
// Operations
self.addMaterial = function() {
self.materials.push(new addMaterial());
}
self.removeMaterial = function(material) { self.materials.remove(material) }
}
ko.applyBindings(new documentViewModel());
Here's my HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script type='text/javascript' src='knockout-2.2.0.js'></script>
</head>
<body>
<div class="container">
<table class="table table-bordered">
<thead>
<tr>
<th>Item</th>
<th>Quantity </th>
<th>Rate</th>
<th>Total</th>
</tr>
</thead>
<tbody "foreach: materials">
<tr class="info">
<td><input data-bind="value: name" /></td>
<td><input data-bind="value: quantity" /></td>
<td><input data-bind="value: rate" /></td>
<td data-bind="text: formattedTotal"></td>
<td>Remove</td>
</tr>
</tbody>
</table>
<button data-bind="click: addMaterial, enable: materials().length < 5">Add Row</button>
<h3 data-bind="visible: totalSurcharge() > 0">
Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span>
</h3>
</div>
</body>
<script type='text/javascript' src='application.js'></script>
</html>
I checked the console error on the browser but am not getting any error. Any idea what am I doing wrong?
I think you intended to bind the materials to the table body, this is not right:
<tbody "foreach: materials">
It should be:
<tbody data-bind="foreach: materials">
Once that is fixed, everything else appears to work.
fiddle

Categories