I am using HTML and JavaScript to develop a simple CRUD webpage and the data is stored in Firebase Realtime Database. I have successfully tabulated all data from Firebase into an HTML table. The problem now is I want to have a function in which I can simply remove a child by clicking the "Delete" button. I keep getting this error:
Uncaught ReferenceError: M1adl3vYm0j1Dvcj43R is not defined at HTMLInputElement.onclick (test.html:1)
Please help me. Thanks. Here is my code:
HTML:
<table>
<tr>
<td>ID:</td>
<td><input type="text" name="id" id="user_id"></td>
</tr>
<tr>
<td>User Name:</td>
<td><input type="text" name="user_name" id="user_name"></td>
</tr>
<tr>
<td colspan="2">
<input type="button" value="Save" onclick="save_user();"/>
<input type="button" value="Update" onclick="update_user();" />
<input type="button" value="Delete" onclick="delete_user();" />
</td>
</tr>
</table>
<h3>Users List</h3>
<table id="tbl_users_list" border="1">
<tr>
<td>ID</td>
<td>NAME</td>
<td>ACTION</td>
</tr>
</table>
Script:
<script>
var tblUsers = document.getElementById('tbl_users_list');
var databaseRef = database.ref('users/');
var rowIndex = 1;
databaseRef.once('value', function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var childKey = childSnapshot.key;
var childData = childSnapshot.val();
var row = tblUsers.insertRow(rowIndex);
var cellId = row.insertCell(0);
var cellName = row.insertCell(1);
var third = row.insertCell(2);
third.outerHTML="<tr id='row"+rowIndex+"'><td><input type='button' value='Delete' class='delete' onclick='delete_user("+childKey+")'></td></tr>";
cellId.appendChild(document.createTextNode(childKey));
cellName.appendChild(document.createTextNode(childData.user_name));
rowIndex = rowIndex+1;
});
});
function save_user(){
var user_name = document.getElementById('user_name').value;
var uid = firebase.database().ref().child('users').push().key;
var data = {
user_id: uid,
user_name: user_name
}
var updates = {};
updates['/users/'+uid] = data;
firebase.database().ref().update(updates);
alert('The user is created successfully!');
reload_page();
}
function update_user(){
var user_name = document.getElementById('user_name').value;
var user_id = document.getElementById('user_id').value;
var data={
user_id: user_id,
user_name: user_name
}
var updates = {};
updates['/users/'+ user_id] = data;
firebase.database().ref().update(updates);
alert('The user is updated successfully!');
reload_page();
}
function delete_user(childKey){
var key = document.getElementById(row).row.childData;
firebase.database().ref().child('users/'+ childKey+'/').remove();
alert('The user is deleted successfully!');
reload_page();
}
function reload_page(){
window.location.reload();
}
</script>
When creating the markup for your button, you'll need to wrap your childKey variable with quotes.
third.outerHTML="<tr id='row"+rowIndex+"'><td><input type='button' value='Delete' class='delete' onclick='delete_user(\""+childKey+"\")'></td></tr>";
or
third.outerHTML=`<tr id='row${rowIndex}'><td><input type='button' value='Delete' class='delete' onclick='delete_user("${childKey}")'></td></tr>`;
Related
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.
I am relatively new to front.
I managed to make my table dynamic which becomes textarea when clicked and back to static table cell when lose the focus.
What I want to do here is sending the value every time it loses focus.
It does with Ajax, but the value in clicked cell is always disappearing when loses control. it happens at any cell.
Here is my code.
HTML
<body>
<div class="container">
<br>
<h2>English lines are under here</h2>
<h5>Click each row to modify</h5>
<br>
<table id="btable" class="bg-light table table-hover">
<th class= "text-center">No</th>
<th class= "text-center">Word</th>
<th class= "text-center">Dialogue</th>
<th class= "text-center">Practice</th>
<c:forEach items="${list}" var="engboardVO">
<tr>
<td class="bid" data-name="bid">${engboardVO.bid}</td>
<td class="word" data-name="word" data-editable>${engboardVO.word}</td>
<td class="dialogue" data-name="dialogue" data-editable>${engboardVO.dialogue}</td>
<td class="practice" data-name="practice" data-editable>${engboardVO.practice}</td>
</tr>
</c:forEach>
</table>
Script
$("table").on("click", "[data-editable]", function(){
var $el = $(this);
var str = $el.text();
console.log(str);
var $input = $('<textarea rows=5 style="width:500px"/>').val( str );
$el.html($input);
$input.focus();
var field_name = $el.attr('data-name');
var save = function(bid, newWord, newDialogue, newPractice){
var $td = $input.val();
$.ajax({
type : "POST",
url : "/tight",
data : JSON.stringify({
bid : bid,
word : newWord,
dialogue : newDialogue,
practice : newPractice
}),
dataType: "json",
success : function(msg){
if (msg["status"] == 'success'){
$input.replaceWith($td);
} else {
alert("Fail");
$input.replaceWith($el);
}
},
error : function(msg) {
alert("ajax fail to get data from server");
}
});
};
$($input).blur(function(){
var bid = $(this).closest('tr').find('td.bid').text();
var newWord = $(this).closest('tr').find('td.word').text();
var newDialogue = $(this).closest('tr').find('td.dialogue').text();
var newPractice = $(this).closest('tr').find('td.practice').text();
console.log(newPractice);
save(bid, newWord, newDialogue, newPractice)
})
});
We cannot use .text() on input and textarea, in which case we would have to use the function .val().
I noticed that you stored the field name but never used it so it would come in handy when trying to get the value of the field that is in edit mode.
Below is a working snippet
$("table").on("click", "[data-editable]", function(){
var $el = $(this);
if ($el.find("textarea").length)
return;
var str = $el.text();
console.log(str);
var $input = $('<textarea rows=5 style="width:500px"/>').val( str );
$el.html($input);
$input.focus();
var field_name = $el.attr('data-name');
var save = function(bid, newWord, newDialogue, newPractice){
var $td = $input.val();
$input.replaceWith($td);
alert("saving bid: " + bid + ", newWord: " + newWord + ", newDialougue: " + newDialogue + ", newPractice: " + newPractice);
};
$($input).blur(function(){
var row = $(this).closest('tr');
var bid = row.find('td.bid').text();
var newWord = field_name == "word" ? row.find("td.word textarea").val() : row.find('td.word').text();
var newDialogue = field_name == "dialogue" ? row.find("td.dialogue textarea").val() : row.find('td.dialogue').text();
var newPractice = field_name == "practice" ? row.find("td.practice textarea").val() : row.find('td.practice').text();
save(bid, newWord, newDialogue, newPractice)
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="btable" class="bg-light table table-hover">
<th class= "text-center">No</th>
<th class= "text-center">Word</th>
<th class= "text-center">Dialogue</th>
<th class= "text-center">Practice</th>
<tr>
<td class="bid" data-name="bid">100</td>
<td class="word" data-name="word" data-editable>word 1</td>
<td class="dialogue" data-name="dialogue" data-editable>dialogue 1</td>
<td class="practice" data-name="practice" data-editable>practice 1</td>
</tr>
<tr>
<td class="bid" data-name="bid">200</td>
<td class="word" data-name="word" data-editable>word 2</td>
<td class="dialogue" data-name="dialogue" data-editable>dialogue 2</td>
<td class="practice" data-name="practice" data-editable>practice 2</td>
</tr>
</table>
I have an html page and I need to send the contents of a table in a POST.
How do I capture the content of the table using jQuery and pass it to the server (which is running node.js and express.js)?
This is the example of a table in a page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
<script src="scripts/jquery-3.2.1.min.js"></script>
</head>
<body>
<table id=horarios>
<tr>
<td>1 </td>
<td>2 </td>
<td>3 </td>
</tr>
<tr>
<td>4 </td>
<td>5 </td>
<td>6 </td>
</tr>
</table>
<form method=post>
<input type="submit" value="Save">
</form>
</body>
</html>
In the server I would capture that POST with something like:
var bodyParser = require('body-parser');
app.use( bodyParser.json() );
app.use( bodyParser.urlencoded({ extended: true }));
app.post('/mypage', function(req, res){
var content = req.body;
res.render('somepage');
});
You want to send a POST request with body set to $('#horarios').html()
You can do this with jQuery.post()
$.post(url, data, success, respType)
where data is the html string of your table, success is a callback if the server sends a success response, and resType is the type of data your server should send back (i.e. text, html, xml, json, script)
So for your example, try adding this inside a script tag on your html page:
// bind to form submit
$('form').submit(function(){
// get table html
var table = {html: $('#horarios').html()};
// POST the data
$.post('/mypage', table, function(response, textStatus){
// do anything with the response here ...
})
});
You need to convert your table into a data structure. You can achieve this with:
var tbl = $('#horarios tr').map(function(rowIdx, row) {
var rowObj = $(row).find('td').map(function(cellIdx, cell) {
var retVal = {};
retVal['cell' + cellIdx] = cell.textContent.trim();
return retVal;
}).get();
var retVal = {};
retVal['row' + rowIdx] = rowObj;
return retVal;
}).get();
In this way you will pass the table as an array of rows of cells.
$('input[value="Save"]').on('click', function(e) {
//
// prevent form submit
//
e.preventDefault();
//
// collect table data by row X col
//
var tbl = $('#horarios tr').map(function(rowIdx, row) {
var rowObj = $(row).find('td').map(function(cellIdx, cell) {
var retVal = {};
retVal['cell' + cellIdx] = cell.textContent.trim();
return retVal;
}).get();
var retVal = {};
retVal['row' + rowIdx] = rowObj;
return retVal;
}).get();
console.log('-->' + JSON.stringify({table: tbl}));
$.post('/mypage', {table: tbl}, function(data, textStatus, jqXHR) {
console.log('success');
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id=horarios>
<tr>
<td>1 </td>
<td>2 </td>
<td>3 </td>
</tr>
<tr>
<td>4 </td>
<td>5 </td>
<td>6 </td>
</tr>
</table>
<form method=post>
<input type="submit" value="Save">
</form>
If you want the data to send via post, first you have to extract values from the table and i recommend you put it into an array, then send it via ajax post.
$('form').on('submit', function(e) {
e.preventDefault();
var $dataElements = $('#horarios').find('td'),
data = [];
$.each($dataElements, function(i, elem){
data.push($(elem).html());
});
$.ajax({url:'/mypage', method: 'POST', data: {data:JSON.stringify(data)}});
});
In other hand if you only want to send the html just send it using $('#horarios').html() instead of loop through elements and add it to the post data.
I hope it helps...
I am trying to create a row of text boxes dynamically through Javascript and read the values of the textbox in JSON. Later,I have to read JSON and display the values in textarea and this should achieved only though jquery and javascript.
I am able to create the text boxes dynamically but I am unable to read the values in JSON. When I use the jQuery part(mentioned below),the javascript to dynamically create textboxes is not working.Any suggestions please.
<table id="myTable">
<th>Name</th>
<th>Age</th>
<th>Gender</th>
<th>Occupation and Employer</th>
<th>Add</th>
<tr>
<td><input type="text" id="txtName" /></td>
<td><input type="text" id="txtAge" /></td>
<td><input type="text" id="txtGender" /></td>
<td><input type="text" id="txtOccupation" /></td>
<td><input type="button" id="btnAdd" class="button-add" onClick="insertRow()" value="add"></input></td>
<td><input type="button" id="btnSave" class="button-add" value="Save"></input> </td>
</tr>
</table>
<script>
var index = 1;
function insertRow()
{
var table=document.getElementById("myTable");
var row=table.insertRow(table.rows.length);
var cell1=row.insertCell(0);
var t1=document.createElement("input");
t1.id = "txtName"+index;
cell1.appendChild(t1);
var cell2=row.insertCell(1);
var t2=document.createElement("input");
t2.id = "txtAge"+index;
cell2.appendChild(t2);
var cell3=row.insertCell(2);
var t3=document.createElement("input");
t3.id = "txtGender"+index;
cell3.appendChild(t3);
var cell4=row.insertCell(3);
var t4=document.createElement("input");
t4.id = "txtOccupation"+index;
cell4.appendChild(t4);
index++;
}
$(document).ready(function(){
$("#btnsave").click(function ()
{
alert("Hi");
var dataToSend={
'Name':[],
'Age':[]};
dataToSend.Name.push({$("txtName").val().trim()});
dataToSend.Age.push({$("txtAge").val().trim()});
localStorage.setItem('DataToSend', JSON.stringify(DataToSend));
var restoredSession = JSON.parse(localStorage.getItem('dataToSend'));
// Now restoredSession variable contains the object that was saved
// in localStorage
console.log(restoredSession);
alert(restoredSession);
});
});
JSFIddle:http://jsfiddle.net/S7c88/
Since you are using jQuery you can greatly simplify the whole process by using methods like clone().
Here's a working example where I created one array of row objects. Since you aren't doing this in a form, I removed the ID's and just used data-name.
var $row;
function insertRow() {
$('#myTable').append($row.clone());
}
$(function () {
$row = $('tr').eq(1).clone(); /* clone first row for re-use*/
$('#myTable').on('click', '.btnSave', function () {
var dataToSend = [];
$('tr:gt(0)').each(function () {
var data = {};
$(this).find('input').each(function () {
data[$(this).data('name')] = this.value
});
dataToSend.push(data);
});
/* display data in textarea*/
$('#output').val(JSON.stringify(dataToSend, null, '\t'))
});
}) ;
I changed your input type=button to button to take advantage of using input selector while looping rows to create data and not have to filter out the buttons
Your demo has invalid html, missing <tr> for top set of <th>
DEMO
Some areas where you were going wrong:
$("txtName") Invalid selector
No row references in attempt to gather data
This is my code:
function deleteHostTable(src) {
var table = src.parentNode.parentNode.parentNode;
if(table.rows.length > 1) {
table.deleteRow(src.parentNode.parentNode);
}
}
function addHost(src) {
var table = src.parentNode.parentNode.parentNode;
var newRow = table.insertRow(table.rows.length-1);
var cell = newRow.insertCell(newRow.cells.length);
cell.innerHTML = '<input type="hidden" name = "vtierIdH" value = "vtierId" />'
cell = newRow.insertCell(newRow.cells.length);
cell.innerHTML = '<img src="images/minus.gif" onclick="deleteHostTable(this);return false;"/>';
cell = newRow.insertCell(newRow.cells.length);
cell.className = "pagetitle";
cell.innerHTML = '<input type = "text" value="hstst" />';
}
</script>
<html>
<table id="host#1" index="1">
<tr>
<td colspan="10">
<h2 align="left" class="pagetitle">Sub Account Hosts:</h2>
</td>
</tr>
<tr>
<input type="hidden" name="vtierIdH" value="<%=vtierId %>" />
<td><button id="minus" onclick="deleteHostTable(this);"/></td>
<td class="pagetitle"><input type="text" value="hstst" /></td>
</tr>
<tr>
<td><button onclick="addHost(this);"></td>
</tr>
</table>
</html>
Now, when i click the button corresponding to a button, this code deletes the uppermost row
and not the row corresponding to that button which is clicked. How can i delete the row corresponding to the button in that row?
Just change your remove function to
function deleteHostTable(src) {
var row = src.parentNode.parentNode;
row.parentNode.removeChild(row);
}
The reason it's not working with deleteRow is that it expects the index of the row to be passed while you are passing an object.
You must pass "index" to the table.deleteRow function, not the element.
function deleteHostTable(src) {
var table = src.parentNode.parentNode.parentNode;
var row = src.parentNode.parentNode;
for(var i = table.rows.length; i--; )
{
if ( table.rows[i] == row )
{
table.deleteRow(i);
return;
}
}
}
this function should work.
You also can use src.parentNode.parentNode.parentNode.removeChild(src.parentNode.parentNode)