How to handle events in dynamic elements? - javascript

I want to create a dynamic questionnaire, loading the next question dynamically, but when I load the second question, the event of the button next2 doesn't respond as if there were no event.
I think it's because I load the input with a JavaScript function. What do I have to do to make it work?
$(document).ready(function() {
var question2 = `
<form>
<input type="number" id="age" placeholder="age">
<input type="submit" id="next2">
</form>
`;
var question3 = `
<form>
<input type = "email" id="email" placeholder="email">
<input type="submit" id="next3">
</form>
`;
$('#next').click(function(e) {
e.preventDefault();
console.log(1);
$(".questions").html(question2);
});
$("#next2").click(function(e) {
e.preventDefault();
$(".questions").html(question3);
});
$("#next3").click(function() {
alert('Cool');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<div class="questions">
<form>
<input type="text" id="name" placeholder="Name">
<button type="submit" value="Next" id="next">Next</button>
</form>
</div>
</html>

You should use $(document). It is a function trigger for any click event in the document. Then inside you can use the jquery on("click","#idname",somefunction), where the second argument specifies which specific element to target. In this case every element inside the body.
$(document).on('click', '#next', function(e) {
e.preventDefault();
$(".questions").html(question2);
});

You only need one event handler for all this, not multiple.
You are inserting the HTML into the element with the class questions with $(".questions").html. Given that you should hook the event handlers to that element with the questions class to be as close to the element as possible (not make it traverse the entire DOM looking for things in the events.
Here I took the CURRENT html and saved it to myApp which I created to hold stuff and not pollute the global namespace; Then I cycle back to it on the last. Odd that you have both button and input type submit but I also handle that. Since these are submit buttons in a form, I added the submit event in case that is how it gets triggered.
$(function() {
let myApp = {};
myApp.question2 = ` <form>I am 2
<input type="number" id="age" placeholder="age">
<input type="submit" id="next2" data-nextthing="question3">
</form>
`;
myApp.question3 = ` <form>I am 3
<input type = "email" id="email" placeholder="email">
<input type="submit" id="next3" data-nextthing="question1">
</form>
`;
myApp.question1 = $(".questions").html(); // just to store it
$(".questions")
.on('click submit', 'form, button[type="submit"], input[type="submit"]', function(event) {
event.preventDefault()
let d = $(this).data('nextthing');
$(event.delegateTarget).html(myApp[d]);
return false;
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="questions">
<form>
<input type="text" id="name" placeholder="Name">
<button type="submit" value="Next" id="next" data-nextthing="question2">Next</button>
</form>
</div>

Related

Why this code is working only with button type attribute?

I have code where on click i am putting value in the input on the form.
This code here works fine.Will put value in the input.
<form>
<label for="fname">First name:</label><br>
<input id="fname" type="text" id="fname"><br>
<button id="btn" type="button">Submit</button>
</form>
var inputs = document.getElementsByTagName("input");
var submitButton = document.getElementById("btn");
submitButton.addEventListener("click" , function() {
inputs[0].value = "fill in value in the input";
})
But my questions is why if i use
<button id="btn">Submit</button>
OR
<input id="btn" type="submit" value="Submit">
instead of
<button id="btn" type="button">Submit</button>
like in the first example
THEN the input will be not filled with the desired value from the JS.
When i click the button for one milisecond the input gets the value and then disappear.
You add the click EventListener for the element with ID btn. <input type="submit" value="Submit"> does not have ID btn, and the eventListener is not applied to it. <input id="btn" ...> should work.
For <button id="btn">Submit</button>, it defaults to type="submit", so the page is reloaded when you click it. You could use e.preventDefault() in the click handler to stop that if you wanted.

How to prevent function call on submit form if required fields are not filled out?

I have form with required inputs, it actually sees empty field and shows message, but it calls function from submit button
<form action="">
<input required id="1" type="text">
<button type="submit" onclick="calculate()">Calculate</button>
</form>
An onclick listener will run whenever the button is clicked, no matter what.
You want the function to run only when the form starts to be submitted, so attach a submit listener to the form instead:
<form action="" onsubmit="calculate()">
<input required id="1" type="text">
<button type="submit">Calculate</button>
</form>
const calculate = (e) => {
console.log('calculating');
}
<form action="" onsubmit="calculate()">
<input required id="1" type="text">
<button type="submit">Calculate</button>
</form>
If at all possible, it would be much better to attach the event listener properly using Javascript instead of an inline HTML attribute:
document.querySelector('form').addEventListener('submit', calculate);
const calculate = (e) => {
e.preventDefault();
console.log('calculating');
};
document.querySelector('form').addEventListener('submit', calculate);
<form action="">
<input required id="1" type="text">
<button type="submit">Calculate</button>
</form>

JS input validation submit disabled for separate instances

I need each instance of input and submit to operate independently. What is the best way to handle multiple instances where each submit is connected to it's own set of inputs?
Since they are unrelated, would data-attributes be the best solution?
$(document).ready(function() {
validate();
$('input').on('keyup', validate);
});
function validate() {
var inputsWithValues = 0;
var myInputs = $("input:not([type='submit'])");
myInputs.each(function(e) {
if ($(this).val()) {
inputsWithValues += 1;
}
});
if (inputsWithValues == myInputs.length) {
$("input[type=submit]").prop("disabled", false);
} else {
$("input[type=submit]").prop("disabled", true);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item1">
<div><input type="text" name="name" autocomplete="off" required/></div>
<input type="submit" value="Submit 1" />
</div>
<div class="item2">
<div><input type="text" name="name" autocomplete="off" required/></div>
<div><input type="text" name="name" autocomplete="off" required/></div>
<input type="submit" value="Submit 2" />
</div>
I think your intuition about using data attributes works great here.
var allButtons = document.querySelectorAll("input[type=submit]");
allButtons.forEach(button => {
button.addEventListener("click", () => {
var inputSet = button.getAttribute("data-input-set");
var inputs = document.querySelectorAll("input[type='text'][data-input-set='" + inputSet + "']");
});
});
In the following code, when an input button is pressed, it will fetch all the inputs with the corresponding "input-set" tag.
Preferred way
I think best solution would be use form -tag as it is created for just this use case HTML Forms.
<form id="form-1">
<input type="text"/>
<input type="submit>
</form>
<form id="form-2">
<input type="text"/>
<input type="submit>
</form>
You can also bind custom Form on submit event handlers and collect form data this way.
$('#form-1').on('submit', function(event){
event.preventDefault(); // Prevent sending form as defaulted by browser
/* Do something with form */
});
Possible but more bolt on method
Alternative methods to this would be to create your own function's for collecting all relevant data from inputs and merge some resonable data object.
I would most likely do this with giving desired class -attribute all inputs I would like to collect at once eg. <input type="text" class="submit-1" /> and so on. Get all elements with given class, loop through all them and save values into object.
This requires much more work tho and form -tag gives you some nice validation out of the box which you this way have to do yourself.

Change (immediatly) submit button text if any form input change [JS]

How can I change immediately the submit button text if any form input change?
//This applies to whole form
$('#test').change(function() {
$("#send").prop("value","Change");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form id="test">
<input id="Input1" value="Input1" />
<input id="Input2" value="Input2" />
<input type="submit" id="send" value="Send" />
</form>
Here, the button text change after the cursor leave the input.
Live example : http://jsfiddle.net/rgg3A/56/
Use input event
Use :input Selector, Selects all input, textarea, select and button elements
$('#test').find(':input').on('input', function() {
document.getElementById('send').value = this.value;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<form id="test">
<input id="Input1" value="Input1">
<input id="Input2" value="Input2">
<input type="submit" id="send" value="Send">
</form>
You need to put the listener on the inputs themselves, in this case attach it to the onKeyDown event:
$('input').on("keydown", function() {
send.value = "Change";
});
Updated Fiddle
A solution requiring minimal change would be to use the keyup event. I.e.
$('#test').keyup(function() {
send.value = "Change";
});
This way, typing in any of the input fields within the #test parent will trigger the event.
You can do it by using jquery input event and selector.
$('input').on("keydown", function() {
$('#send').val(this.value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form id="test">
<input id="Input1" value="Input1">
<input id="Input2" value="Input2">
<input type="submit" id="send" value="Send">
</form>
As your original question did not mention JQuery directly except by it's use as a selector, this one left me hanging for a proper JavaScript answer.
So this answer is the same as the other examples, but using just plain ol' JavaScript. Uses the input event, just as the other answers do.
document.getElementById('test').addEventListener('input', function(e) {
document.getElementById('send').value = e.target.value;
});
<form id="test">
<input id="Input1" value="Input1">
<input id="Input2" value="Input2">
<input type="submit" id="send" value="Send">
</form>
The difference here is that it is listening for bubbled events on the form element proper, registers an event listener only once (instead of applying the same event listener to multiple elements), and using the Event.target property to figure out which element was modified.

call a method on form submit with list of arguments

I am catching event of form submit and adding divs to the DOM, code http://jsfiddle.net/testtracker/7rkX4/7/
now i want to pass some arguments to the function like name of the commenter, time comment was added etc. I want it to be something like this.
html
<form onsubmit="addComment('john deo','post_id')">
<input ......>
<input ......>
</form>
javascript
function addComment(commenter_name,post_id){
perform operation....
}
The code you posted works fine. The reason it would not work in jsfiddle is because your functions are declared in a document.ready type of block by default (see the onLoad in the drop down on the left?)
The proper way to bind event handlers would be to bind them in javascript. This would avoid the scope problem.
If you need to get an inline event handler working, you can explicitly define your function as global:
window.addComment = function (commenter_name,post_id){
perform operation....
};
You can store the name of the commenter in html for example.
Try this (see demo: http://jsfiddle.net/7rkX4/8/).
HTML
<div class="post">
<ul class="comments"></ul>
<div class="comment_entry">
<form method="post" action="#">
<input type="hidden" name="name" value="Neha" />
<input type="text" name="comment" placeholder="Leave comment" />
<input type="submit" value="submit" />
</form>
</div>
</div>
<div class="post">
<ul class="comments"></ul>
<div class="comment_entry">
<form method="post" action="#">
<input type="hidden" name="name" value="Danil" />
<input type="text" name="comment" placeholder="Leave comment" />
<input type="submit" value="submit" />
</form>
</div>
</div>​
JavaScript
$(document).ready(function () {
$('.comment_entry form').submit(function (e) {
e.preventDefault();
var name = $('input[name="name"]', this).val();
var comment = $('input[name="comment"]', this).val();
$(this).parent().prev().append('<li><a class="commenter_name" href="/">' + name + '</a><br />' + comment + '</li>');
});
});​
If I understand correctly you want to add some variable-value pairs to the form on submit. Why not add some input fields to your form with type="hidden", then you can modify their values in your javascript code as you like.

Categories