Attaching event handlers to dynamically generated elements - javascript

I have the following HTML :
<button type="button" id="Button">Go</button>
<div id="validation"></div>
I'm trying to add event handlers to dynamically generated elements in the following way :
Click button -> Generate element X inside div #validation -> Attach event handler to element X
$(document).ready(function(){
ID = 1;
$("#Button").click(function(){
/*generate new div inside div #validation with id #validationID
1st one would be #validation1
it contains a form with name accepterID and a button with name refuserID
1st ones would be accepter1 and refuser1*/
var newline = `
<div id="validation${ID}">
<form name="accepter${ID}">
<input type="hidden" name="name" value="phoegasus">
<button type="submit" value="valider">
</form>
<button name="refuser${ID}">refuser</button>
</div>
`
$("#validation").append(newline);
/*attach event handlers to the generated elements
1st iteration would attach handlers to accepter1 and refuser1 */
$("#validation").on('submit',"form[name^='accepter"+ID+"']",function(e){
$("#validation" + ID).remove();
//remove div validationID after submitting form
});
$("#validation").on('click',"button[name^='refuser"+ID+"']",function(){
$("#validation" + ID).remove();
//remove div validationID
});
ID++;
});
});
When I submit the form or I click the generated button I want to remove the div that contains them. If I press the button refuser1, it should delete the div #validation1.
When the elements are generated the handlers aren't attached to them.
The code doesn't work when it's executed during the onclick event but when I execute it in the navigator console it works.
I tried using DOMSubtreeModified on the div with id #validation, but it didn't work.

you can manage it by using a class (or another element) in second argument of your on function.
For that, DO NOT declare your event listeners inside your add event.
This is a full working example :
$("#validation").on('submit',"form.validation-form",function(e){
e.preventDefault();
console.log('form', $(this).attr('data-id'), ' submitted');
});
$("#validation").on('click',"button.validation-refuser",function(){
console.log('clicked on refuser for form ', $(this).attr('data-value'));
//code
});
var ID = 1;
$('#my-adder').on('click', function () {
$('#validation').append('<form name="accepter'+ID+'" class="validation-form" data-id="'+ID+'"><input type="text" placeholder="my text field" /><button class="validation-refuser" name="refuser'+ID+'" data-value="'+ID+'">Refuser button</button><button type="submit">SUBMIT</button></form>');
ID++;
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="validation">
<form name="accepter0" class="validation-form" data-id="0">
<input type="text" placeholder="my text field" />
<button type="button" class="validation-refuser" name="refuser0" data-value="0">Refuser button</button>
<button type="submit">SUBMIT</button>
</form>
</div>
<button id="my-adder">ADD A FORM</button>
Hope it helps

Related

Change button value after clicking on it [duplicate]

This question already has answers here:
Changing button text onclick
(19 answers)
Closed 4 years ago.
I have a function which returns bootstrap row and every row contains input field, textarea and remove button.
So I have multiple bootstrap rows as I am calling function for various time. After clicking on remove button I am changing border color of input and textarea just to indicate that I am not taking it into consideration. I have made remove button to work as toggle button so that it will add and remove error class that I am assigning to input and textarea.
Now I want to change the value of 'Remove' button to 'Add'. So that when I click on 'Add' button it will remove the style of input and textarea and it means that I can take those values into consideration.
function GetDynamicTextBox(value, tag) {
return'<div class="col-lg-4"><input class="form-control" type="text" value="'+tag+'" name="typetag" id="tags" data-role="tagsinput"/></div>'+'' +
'<div class="col-lg-6"><textarea class="form-control issuetext" name="comment" id="" cols="" rows="">'+value+'</textarea></div>'+
'<div class="col-lg-2">'+
'<input type="button" value="Remove" class="remove btn btn-default" /></div>'
}
$("body").on("click", ".remove", function () {
$(this).closest('#issue').find('.bootstrap-tagsinput').toggleClass('error')
$(this).closest('#issue').find('.issuetext').toggleClass('error')
});
<div class='row'id="issue">
<div class="col-lg-4">
<input class="form-control" type="text" value="'+tag+'" name="typetag"
id="tags" data-role="tagsinput"/></div>
<div class="col-lg-6">
<textarea class="form-control issuetext" name="comment" id="" cols=""
rows="">'+value+'</textarea></div>
<div class="col-lg-2">
<input type="button" value="Remove" class="remove btn btn-default" /></div>
</div>
It's pretty straightforward. Just add a click event to the button. The click event will give you an event (e) and you can then call the standard .innerText property on the element to set it. No need for jQuery here...
const btn = document.getElementById('testButton');
let clickCount = 0;
btn.addEventListener('click', (e) => {
e.currentTarget.innerText += clickCount++;
});
<button type="text" id="testButton">Initial Value</button>
You can add an event listener to the button and change its textContent according to the value of a global variable.
<button id="removeOrAdd">Remove</button>
<script>
var remove = true;
document.getElementById("removeOrAdd").addEventListener("click", function(e){
if(remove){
this.textContent = "Add";
remove = false;
} else {
this.textContent = "Remove";
remove = true;
}
});
</script>

Observe Form Submission

In my application I need to submit forms via JavaScript. I know that I can do that with this code:
[...document.querySelectorAll('form')].forEach(form => {
form.addEventListener('submit', e => {
//doing the processing here
e.preventDefault();
})
})
From the server I get completely generated forms as HTML, which I inject into the DOM (or delete them from there), whenever necessary. By doing so, the registered event handlers stop to work, because the form element is either deleted or not registered.
Is it possible to register a global »Submission Listener«, comparable to that:
window.addEventListener('click' e => { … });
what will never be removed if the DOM changes, or will I have to register the submission handlers each time the DOM changes?
Is not a dublicate, because the mentioned delegation strategy is what I am looking for, but not for click events, for submission events instead.
You can definitely catch submit events as they bubble up, so what you want can be achieved by listening from a parent element that is always present as the dynamic forms are added and removed. I like doing this thing with a wrapper element with an ID, as opposed to listening a the body or html level. Here's a very simple example using just vanilla js. Codepen here: http://codepen.io/bsidelinger912/pen/RGbWYb
HTML:
<div id="form-wrapper">
<h2>Form 1</h2>
<form id="form1">
<input name="test" placeholder="enter something" />
<input type="submit" value="submit" />
</form>
<h2>Form 2</h2>
<form id="form2">
<input name="test" placeholder="enter something" />
<input type="submit" value="submit" />
</form>
</div>
<button id="form-adder">
+ Add a form
</button>
Javascript
var formWrapper = document.getElementById('form-wrapper');
// capture the submit event in the parent div
formWrapper.addEventListener("submit", function(e) {
e.preventDefault();
console.log('submit captured');
var thisForm = e.srcElement || e.originalTarget;
console.log('form id:' + thisForm.id);
console.log(thisForm.test.value);
});
// dynamically add divs and see we can still capture the submit
var divNum = 3;
function addDiv(e) {
e.preventDefault();
formWrapper.innerHTML += '<h2>Form ' + divNum + '</h2>\
<form id="form' + divNum + '">\
<input name="test" placeholder="enter something" />\
<input type="submit" value="submit" />\
</form>';
divNum++;
}
document.getElementById('form-adder').addEventListener('click', addDiv);

How to remove input group in bootstrap?

This is what I have right now. I'm trying to add fields to the form dynamically using jQuery add() and append() method. But I want to remove the particular added field when the remove button is clicked.
<div class="col-md-12">
<h3>Added Description Fields</h3>
<div class="col-md-12" id="descFields">
</div>
</div>
JS
$(document).ready(function() {
console.log(descFields);
$('#addDesc').click(function(e) {
var descFields = $('#descFields');
var descLabel = $('#descLabel').val();
var large = '<div class="form-group" id="descField"><div class="input-group"><input type="text" class="form-control" placeholder="Enter Value For ' + descLabel + '" /><span class="input-group-btn"><button class="btn btn-danger" id="removeDesc" type="button">Remove</button></span></div>';
descFields.add(large).appendTo(descFields);
e.preventDefault();
});
$('#removeDesc').click(function(e) {
$(this).remove();
});
});
When the user click on the #removeDesc button , the the field that is added should be removed. I cannot figure out how to achieve this.
There are many ways of doing this, but the simpler for your problem is this one:
$(document).ready(function() {
console.log(descFields);
$('#addDesc').click(function(e) {
var descFields = $('#descFields');
var descLabel = $('#descLabel').val();
var large = '<div class="form-group" id="descField"><div class="input-group"><input type="text" class="form-control" placeholder="Enter Value For ' + descLabel + '" /><span class="input-group-btn"><button class="btn btn-danger" id="removeDesc" type="button">Remove</button></span></div>';
descFields.add(large).appendTo(descFields);
e.preventDefault();
});
$('#descFields').on('click', '#removeDesc', function(e) {
$(this).parents('.form-group').remove();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="descLabel"/>
<button id="addDesc">Add Desc</button>
<div class="col-md-12">
<h3>Added Description Fields</h3>
<div class="col-md-12" id="descFields">
</div>
</div>
Your problem is in the callback to delete the rows. When the document has finished loading you are trying to attach a click event to an object #removeDesc that is still not present in the DOM because it's created on the fly when the user clicks the #addDesc.
That's why you should use:
$('#descFields').on('click', '#removeDesc', function(e) {
$(this).parents('.form-group').remove();
});
As #vijayP suggested before you can use the on() to attach an event handler to the container where you'll be adding the object that is still not present in the DOM. Then you pass in the query selector as the second parameter to filter in execution time which of its children will trigger the event and execute the callback.
My additional trick is that I'm using .parents('.form-group') to select the div containing the group and remove all of the fields that were added instead of removing only the button.
Happy coding!
Add click event for remove button like follows:
$(document).on("click","#removeDesc",function(e) {
$(this).remove();
});

Editing and Deleting Dynamically Generated List Items in jQuery Todo List App

I'm attempting to create a todo list app in HTML, CSS, and jQuery, and I'd like to be able to add, edit, and delete tasks. I'm able to add new tasks to the list, but I'm unable to edit or delete them when I click the "Edit" and "Delete" buttons, and I'm not sure why it isn't working.
I've uploaded a copy of my code to jsfiddle (https://jsfiddle.net/LearningToCode/nndd1byt/6/) and included a copy below.
Any help you can offer would be greatly appreciated. Thanks!
Expected Behavior:
Clicking the "Delete" button next to a task should allow a user to delete that task.
Clicking the "Edit" button next to a task should allow a user to edit the text of that task.
Actual Behavior:
Clicking the "Delete" button does nothing.
Clicking the "Edit" button does nothing.
Code Examples:
HTML
<h1>Todo List</h1>
<input type="text" id="enter_task" placeholder="Enter Task">
<input type="submit" id="add" value="Add Task">
<p>
<ul id="todo_list">
</ul>
</p>
JavaScript
function enter_task () {
var text = $('#enter_task').val();
$('#todo_list').append('<li>'+ text + ' <input type="submit" id="edit" value="Edit">' + '<input type="submit" class="done" id="delete" value="Delete">' +'</li>');
};
$('#edit').click(function(){
$('li').attr('contenteditable','true');
});
$('#delete').click(function(){
$('li').remove();
});
$(function() {
$('#add').on('click', enter_task);
});
The problem is that your delete buttons are dynamically created. During page load, $('#delete') returns an empty set because there's no one there yet. When you finally have list items, their delete buttons are not bound to anything.
What you can do is delegate the event handler to an ancestor that exists during page load. Events "bubble" to its ancestors, making ancestors aware that you clicked a descendant. In this case, you can attach the handler to <ul>, and have it listen for clicks on .delete.
In addition, IDs are supposed to be unique. You can only have one of them on the page. Having more than one might lead to unpredictable behavior. Use classes instead.
Also, $('li') will select all <li> on the page. You might want to scope down your selection. You can remove the <li> containing your button using $(this).closest('li').remove()
The code you need should be this, plus add delete as the button class. Apply the same concept for the edit.
$('#todo_list').on('click', '.delete', function(){
$(this).closest('li').remove()
});
I've created a working example - https://jsfiddle.net/nndd1byt/7/
function enter_task () {
var text = $('#enter_task').val();
$('#todo_list').append('<li>'+ text + ' <input type="submit" class="edit" value="Edit">' + '<input type="submit" class="done delete" value="Delete">' +'</li>');
};
$('#todo_list').on('click', '.edit', function(){
$(this).parent().attr('contenteditable','true');
});
$('#todo_list').on('click', '.delete',function(){
$(this).parent().remove();
});
$(function() {
$('#add').on('click', enter_task);
});
Try adding the jquery function initializers into the enter_task function, this way they are refreshed with each new line.
var counter = 1;
function enter_task () {
var text = $('#enter_task').val();
$('#todo_list').append('<li><span>'+ text + ' </span><input type="submit" id="edit' + counter + '" value="Edit">' + '<input type="submit" class="done" id="delete' + counter + '" value="Delete">' +'</li>');
$('#edit' + counter).click(function(){
$(this).prev().attr('contenteditable','true');
$(this).prev().focus();
});
$('#delete' + counter).click(function(){
$(this).parent().remove();
});
counter++;
};
$(function() {
$('#add').on('click', enter_task);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Todo List</h1>
<input type="text" id="enter_task" placeholder="Enter Task">
<input type="submit" id="add" value="Add Task">
<p>
<ul id="todo_list">
</ul>
</p>

Input text value into a div?

Say I have this text box:
<input type="text" id="myText" placeholder="Enter Name Here">
Upon pressing a button, I would like to send the value entered into this div:
<div id="text2"></div>
I'm not entirely sure how to do this. Do I create a function and call it to the div? How would I do that?
Could someone clear this up for me? Thanks.
Add an onclick to your button:
<input type="button" id="somebutton" onclick="addText()">
Then write the javascript:
function addText()
{
document.getElementById('text2').innerHTML = document.getElementById('myText').value;
}
Solution using onclick event:
<input type="text" id="myText" placeholder="Enter Name Here">
<div id="text2"></div>
<button id="copyName" onclick="document.querySelector('#text2').innerHTML = document.querySelector('#myText').value" value="Copy Name"></button>
JSFiddle: http://jsfiddle.net/3kjqfh6x/1/
You can manipulate the content inside the div from javascript code. Your button should trigger a function (using the onclick event), which would access the specific div within the DOM (using the getElementById function) and change its contents.
Basically, you'd want to do the following:
<!DOCTYPE html>
<html>
<script>
function changeContent() {
document.getElementById("myDiv").innerHTML = "Hi there!";
}
</script>
<body>
<div id="myDiv"></div>
<button type="button" onclick="changeContent()">click me</button>
</body>
</html>
Mark D,
You need to include javascript to handle the button click, and in the function that the button calls, you should send the value into the div. You can call $("#myText").val() to get the text of the text box, and $("#txtDiv").text(txtToAppend) to append it to the div. Please look at the following code snippet for an example.
function submitTxt() {
$("#txtDiv").text($("#myText").val())
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="myText" placeholder="Enter Name Here">
<button onclick = "submitTxt()"> Submit </button>
<div id="txtDiv"> </div>
HTML could be:
<input type='text' id='myText' placeholder='Enter Name Here' />
<input type='button' id='btn' value='click here' />
<div id='text2'></div>
JavaScript should be external:
//<![CDATA[
var pre = onload; // previous onload? - window can only have one onload property using this style of Event delegation
onload = function(){
if(pre)pre();
var doc = document, bod = doc.body;
function E(e){
return doc.getElementById(e);
}
var text2 = E('text2'); // example of Element stored in variable
E('btn').onclick = function(){
text2.innerHTML = E('myText').value;
}
}
//]]>
I would recommend using a library like jQuery to do this. It would simplify the event handling and dom manipulation. None the less, I will include vanilla JS and jQuery examples.
Assuming the HTML in the body looks like this:
<form>
<input id="myText" type="text" placeholder="Enter Name Here">
<br>
<input type="submit" id="myButton">
</form>
<div id="text2"></div>
The Vanilla JS example:
//Get reference to button
var myButton = document.getElementById('myButton');
//listen for click event and handle click with callback
myButton.addEventListener('click', function(e){
e.preventDefault(); //stop page request
//grab div and input reference
var myText = document.getElementById("myText");
var myDiv = document.getElementById("text2");
//set div with input text
myDiv.innerHTML = myText.value;
});
When possible avoid using inline onclick property, this can make your code more manageable in the long run.
This is the jQuery Version:
//Handles button click
$('#myButton').click(function(e){
e.preventDefault(); //stop page request
var myText = $('#myText').val(); //gets input value
$('#text2').html(myText); //sets div to input value
});
The jQuery example assumes that you have/are adding the library in a script tag.

Categories