How to write an onclick function for a dynamically generated button - javascript

I have some buttons that look like this.
It is a "whitelist" of websites. I'd like for the button to remove the corresponding site from the whitelist.
However, since these buttons are generated with each addition of a site (entered by the user), I don't know how to get the ElementID to use in my function.
Here is where the button is generated:
var cellWebsite = document.createElement("td");
var website = document.createTextNode(array[i]);
//append cell text to cell, then cell to row (like setting a "stage")
cellWebsite.appendChild(website);
row.appendChild(cellWebsite);
//create a cell & cell text for BUTTON
var cellDelete = document.createElement("td");
var button = document.createElement("BUTTON"); //has its own element
var text = document.createTextNode("x");
button.appendChild(text);
cellDelete.appendChild(button);
row.appendChild(cellDelete);
How do I get the ID so I can write a function for when the X button is clicked? Within that function, how can I get the website that corresponds to that button?
I'm making a Chrome Extension and using chrome's local storage, if it matters.

The easiest way is to add an event listener the button variable like so:
const btn = document.createElement('button');
btn.innerText = "Click me!";
btn.addEventListener('click', function(event) {
console.log('Fired!');
});

I cannot seem to comment since I need 50 rep. for it, but can't you give it an increment? With each add just increment the ID or name with 1, and then u could target the ID or name.

Check the inspection view of your browser and see if id and other attributes are set.
If this didn't work, make use of the form id attribute the index of the element as፡
var x = document.getElementById("myForm").elements[0].value;
If no id provided for form:
var x = document.forms[0].id;
Or
var x = document.forms.item(0).id;

When your element is dynamically created, You should event delegation to handle event.
Event delegation allows you to avoid adding event listeners to specific nodes; instead, the event listener is added to one parent. That event listener analyzes bubbled events to find a match on child elements.
Example:
var counter = -1;
function addRow() {
counter++;
var table = document.getElementById( 'myTable' ),
row = table.insertRow( counter ),
cell = row.insertCell( 0 ),
cellDelete = row.insertCell( 1 ),
button = document.createElement( 'button' ),
text = document.createTextNode( 'X' );
cell.innerHTML = 'wikipedia.org ' + counter;
button.appendChild( text );
cellDelete.appendChild( button );
button.addEventListener( 'click', function ( e ) {
table.deleteRow( e.target.parentNode.parentNode.rowIndex );
counter--
} )
}
body {
margin: 0
}
table {
width: 100%
}
td {
padding: 8px;
border-bottom: 1px solid #ddd
}
td:nth-child(even) {
text-align: right
}
tr:nth-child(odd) {
background-color: #efefef
}
<button type="button" onclick="addRow()">Add new row</button>
<br>
<table id="myTable"></table>

Related

Add onclick to a button with java script [duplicate]

This question already has an answer here:
addEventListener in Javascript triggers the click event automatically
(1 answer)
Closed 1 year ago.
I am creating a list of buttons inside a table, like this:
let tbody = document.createElement("tbody");
tbody.className = "table-responsive";
let id = 0;
for (let c of rows) {
let tr = document.createElement("tr");
tr.className = "table";
for (const v of c) {
let td = document.createElement("td");
td.className = "table";
let txt = document.createTextNode(v);
td.appendChild(txt);
tr.appendChild(td);
}
id++;
let button = document.createElement("button");
button.innerHTML = "ACTUALIZAR DATOS";
button.className = "btn btn-outline-primary";
button.id = id++;
button.onclick = upgradePet();
tr.appendChild(button);
tbody.appendChild(tr);
}
the table shows correctly, but when i try to add the .onclick, but when the table load, it call immediately the function upgradePet() without me clicking it.
i try doing:
button.addEventListener("click", upgradePet());
button.onclick = upgradePet();
but both call the function when the table finish render.
Remove the parentesis from your upgradePet as that represents a function call (meaning you are not just defining the function on the click event, but you're calling it straight away).
So this works fine,
button.onclick = upgradePet;
In case you will ever need to define functions with parameters, you can write them as followed,
button.onclick = () => upgradePet(param);
Remove the parentesis.
addEventListener
onclick
button.addEventListener("click", upgradePet);
button.onclick = upgradePet;
Two things to fix:
Add function objects as event listeners, not the value returned from calling a handler function. The return value is often undefined or, more rarely, a boolean value:
element.addEventListener( eventName, handler); ✔️
element.addEventListener( eventName, handler()); ❌
Do not append a <button> element to a table row - they are not valid child elements of a <tr> element. Create an extra td element, put the button element inside it and append the table data element created to the table row.

Create multiple elements and delete a single one JavaScript

I'm working on a JavaScript project where a user can click a button to create a text element. However, I also want a feature where I can click a different button and the element that was created most recently will be removed, so In other words, I want to be able to click a button to create an element and click a different button to undo that action.
The problem I was having was that I created the element, then I would remove the element using:
element.parentNode.removeChild(element); , but it would clear all of the elements that were created under the same variable.
var elem = document.createElement("div");
elem.innerText = "Text";
document.body.appendChild(elem);
This code allows an element to be created with a button click. All elemente that would be created are under the "elem" variable. so when I remove the element "elem", all element are cleared.
Is there a simple way to remove on element at a time that were all created procedurally?
Thanks for any help
When you create the elements, give the a class. When you want to remove an element, just get the last element by the className and remove it.
The below snippet demonstrates it -
for(let i = 0; i<5; i++){
var elem = document.createElement("div");
elem.innerText = "Text " + i;
elem.className = "added";
document.body.appendChild(elem);
}
setTimeout(function(){
var allDivs = document.getElementsByClassName("added");
var lastDiv = allDivs.length-1;
document.body.removeChild(allDivs[lastDiv]);
}, 3000);
I would probably use querySelectors to grab the last element:
// optional
// this is not needed it's just a random string added as
// content so we can see that the last one is removed
function uid() {
return Math.random().toString(36).slice(2);
}
document.querySelector('#add')
.addEventListener('click', (e) => {
const elem = document.createElement('div');
elem.textContent = `Text #${uid()}`;
document.querySelector('#container').appendChild(elem);
// optional - if there are elements to remove,
// enable the undo button
document.querySelector('#undo').removeAttribute('disabled');
});
document.querySelector('#undo')
.addEventListener('click', (e) => {
// grab the last child and remove
document.querySelector('#container > div:last-child').remove();
// optional - if there are no more divs we disable the undo button
if (document.querySelectorAll('#container > div').length === 0) {
document.querySelector('#undo').setAttribute('disabled', '');
}
});
<button id="add">Add</button>
<button id="undo" disabled>Undo</button>
<div id="container"></div>

How do I create an OnClick Event for a table cell's inner html

I would like to make the text WITHIN a table cell trigger an onclick function using JavaScript. I am able to make the cell itself trigger the onClick event but that is not what I want.
var table = document.getElementById(tableName);
var row = table.insertRow(0);
var cell1 = row.insertCell(0);
cell1.innerHTML = "some text"
//how do I make the text within the innerHTML trigger an onclick event?
The actual text within a table cell cannot be bound to an event listener as such. If the text within the table cell is in another tag ( such as a paragraph, span, div or whatever ) then you can use a slight trick to test for which element triggered the event by comparing the event target and the event currentTarget properties.
You can click anywhere in the cell and nothing will happen unless you click on the paragraph - at which point the target will no longer be the same as the currentTarget that was registered with the event listener. There is, as far as I am aware, no way of doing this with just the raw text within the table cell - and ultimately why would you need to do so anyway?
<table id='banana' border=1 cellpadding='5px' cellspacing='2px'>
<!-- content to follow -->
</table>
<script>
const nl=String.fromCharCode(10);
var id='banana';
var table = document.getElementById( id );
var row = table.insertRow(0);
var cell = row.insertCell(0);
cell.innerHTML = 'This is some basic text';
var p=document.createElement('p');
p.innerText='This is a Paragraph within the table cell';
cell.appendChild( p )
cell.addEventListener( 'click', function(e){
if( e.target != e.currentTarget ) alert( [ 'target: '+e.target, 'currentTarget: '+e.currentTarget, 'text: '+e.target.innerText ].join( nl ) )
});
</script>
Following on from the comment made previously about triggering an event when a user selects text within the table cell, you can possibly try the following:
document.body.addEventListener('mouseup',(e)=>{
alert( 'Text has been selected? '+ window.getSelection() )
});
There is, as I just discovered, a selectionchange event that might be of interest - more information from MDN
Add an event listener to cell1.
cell1.addEventListener("click", function() {
console.log(this.innerText);
})
use onclick for onClick event
cell1.onclick = function ()
{
console.log("onclick");
};
var table = document.getElementById("table");
var row = table.insertRow(0);
var cell1 = row.insertCell(0);
cell1.innerHTML = "some text"
cell1.onclick = function ()
{
console.log("onclick");
};
<table id="table">
</table>

How to know that which button is clicked, if buttons are added dynamically using javascript?

I don't know how to solve that problem, If anyone knows how to solve that then please let me know. If required, then I will send the code personally to figure out the mistakes.
There are two containers: left and right. In Left, there is a from where I take values of title, description and status(active/inactive) from text boxes and radio buttons(active/inactive). Then after pressing submit button all values are filled in table of right-container with edit and delete button attached after clicking submit button every time. I want to delete specific row where delete button is clicked. But I don't know how to access that button while onclick function(doDelete()) is same in all the buttons.
function fillData() {
var table = document.getElementById("myTable");
var counter = table.querySelectorAll('tr').length;
var key = counter;
var row = table.insertRow(counter);
row.id = "row-" + key;
var titleCell = row.insertCell(0);
var descCell = row.insertCell(1);
var statusCell = row.insertCell(2);
var actionCell = row.insertCell(3);
var editButton = document.createElement("button");
editButton.innerText = "Edit";
editButton.id = "edit-" + key;
editButton.setAttribute("onclick", "doEdit()");
var delButton = document.createElement("button");
delButton.innerText = "Delete";
delButton.id = "delete-" + key;
delButton.setAttribute("onclick", "doDelete()");
titleCell.innerHTML = document.getElementById("panel-title").value;
descCell.innerHTML = document.getElementById("panel-description").value;
statusCell.innerHTML = (function () {
var radios = document.getElementsByName("status");
for (i = 0, len = radios.length; i < len; i++) {
if (radios[i].checked) {
return radios[i].value;
}
}
}());
actionCell.appendChild(editButton);
actionCell.appendChild(delButton);
var delBtnArr = document.querySelectorAll('input[type="button"]');
console.log(delBtnArr);
}
Actual Results: After pressing delete button, the whole rows are deleted.
Expected Results: After pressing delete button, the specific row is deleted where button is clicked.
Javascript also sends the assosiated event as parameter and in this way you can get id by using event utilities. You can get the clicked button id as below. By getting that id I think you can also get the associated row. After that you can delete the row.
doDelete(event){
let clickedButtonId = e.target.id;
//get row id. I think you can get it.
document.removeElement(rowId);
}
Event Delegation
Bind/Register the Ancestor to Event
Dynamically added tags cannot bind to an event handler/listener, only tags that have existed since the page was loaded can. So for multiple dynamically added tags such as the buttons you have to find an ancestor tag that they all share incommon and bind it to whatever event you need to listen for. For your buttons it can be the closest ancestor table* (recommended) to the furthest window:
// On-event property. ALWAYS PASS THE EVENT OBJECT
table.onclick = function(event) {...
OR
// Event Listener. Abbreviating the [Event Object][2] is OK, but you must be consistent.
table.addEventListener('click', function(e) {...
Do not use on-event attributes <button onclick="func()"...
✱Technically the closest ancestor is tbody even if you didn't add it to the table, the browser will add it by default.
Use Event.target and Event.currentTarget Properties
Remember to pass the Event Object because you'll need it to...
...find out which button you actually clicked with event.target property.
...get a reference to the table with event.currentTarget property.
...possibly prevent default behavior such as stopping a form from submitting to a server with event.preventDefault() method.
Review the demo, it will have specific details on the event handlers.
Demo
Details commented in demo
var table = document.querySelector("table");
document.forms[0].onsubmit = fillData;
/*
This onevent property handler has two functions note it is bound
to the table NOT the buttons.
There's two conditionals and they only focus on classNames of
either .del or .edit. Once it's determined if the clicked tag has
one of these classes then the appropriate function is called.
If neither class was clicked there's no opportunity for anything
else to act on the click because both conditionals end with
return false thereby terminating the event handler.
*/
table.onclick = function(e) {
if (e.target.className === 'del') {
delRow(e);
return false;
}
if (e.target.className === 'edit') {
editRow(e);
return false;
}
};
function fillData(e) {
var ui = e.target.elements;
e.preventDefault();
var idx = table.rows.length;
var row = table.insertRow();
row.id = 'r-' + idx;
var cell1 = row.insertCell(0);
var data1 = ui.title.value;
cell1.textContent = data1;
var cell2 = row.insertCell(1);
var data2 = ui.desc.value;
cell2.textContent = data2;
var cell3 = row.insertCell(2);
var data3 = ui.chk.checked ? 'Active' : 'Inactive';
cell3.textContent = data3;
var cell4 = row.insertCell(3);
var btns = `
<button class='edit'>📝</button>
<button class='del'>❌</button>`;
cell4.innerHTML = btns;
}
/*
Reference the .closest() row from clicked button
Get that row's id and split() it at the dash and pop() the number.
Then get a reference to the bound ancestor (table) and deleteRow() with the new number you just got.
*/
function delRow(e) {
var row = e.target.closest('tr');
var idx = row.id.split('-').pop();
e.currentTarget.deleteRow(idx);
}
/*
Same as before get the index number from the closest row's id.
Reference the table and use the .rows property and number.
This reference will now allow you to use the .cells property.
Use the .cells property to toggle the contenteditable attribute
on the first three cells.
*/
function editRow(e) {
var row = e.target.closest('tr');
var idx = row.id.split('-').pop();
var R = e.currentTarget.rows[idx];
for (let c = 0; c < 3; c++) {
var cell = R.cells[c];
if (cell.hasAttribute('contenteditable')) {
cell.removeAttribute('contenteditable');
} else {
cell.setAttribute('contenteditable', true);
}
}
}
body {
font: 400 16px/25px Consolas;
display: flex;
justify-content: space-between;
}
fieldset {
width: fit-content
}
input,
label,
textarea {
font: inherit
}
input,
label,
button {
display: inline-block;
height: 25px;
}
#title {
width: 27.5ch;
}
#chk {
display: none;
}
#chk+label::after {
content: '\2610';
font-size: 20px;
vertical-align: middle;
}
#chk:checked+label::after {
content: '\2611';
}
[type='reset'] {
margin-left: 5%
}
td {
min-width: 60px;
border-bottom: 1px solid #000;
height: 25px;
}
tr td:last-child {
border-bottom-color: transparent;
}
button {
width: 35px;
text-align: center;
}
<form id='data'>
<fieldset>
<legend>Enter Data</legend>
<input id='title' type='text' placeholder='Title'><br>
<textarea id='desc' rows='3' cols='25' placeholder='Description'></textarea><br>
<input id='chk' type='checkbox'>
<label for='chk'>Active </label>
<input type='reset'>
<input type='submit'>
</fieldset>
</form>
<hr>
<table></table>

define dynamic width of textbox using DOM approach

i am tyring to insert textboxes to create empty rows but i want first textbox should be of 50px only
i am creating them onclick event of a button using DOM approach
how to define the width with respect to following approach
j is a variable being handled somewhere & cols is no: of columns to be created
for(var t=1;t<=cols;t=t+1)
{
var cell = row.insertCell(t);
var element = document.createElement("input");
element.type = "text";
element.id= 'text['+j+']['+(t)+']';
element.name= 'text['+j+']['+(t)+']';
element.value="";
cell.appendChild(element);
}
some times it may works
element.style.width = width + 'px';
try it once in case the above suggestions fails
or by using this,
element.setAttribute("style","width:50px");
Try the following:
In CSS:
.firsttext
{
width: 50px;
}
In Javascript:
if (t==1)
{
element.className = "firsttext";
}

Categories