first of all I'm trying to create a form where is needed to duplicate some blocks of fields and fields as the user want.
So I have a page where there is a button that after clicking on it duplicates a certain block. The first button works fine!, it duplicates a block without reloading the page when is clicked.
But in that block there are some input fields that I need to duplicate as well.
So when the block is duplicated a new button is added to duplicate fields inside that block.
The problem is that when I click on the second button it reloads the page, instead of just duplicate an input field.
To do this I'm using jquery, code to duplicate the block, this is the code to add the block, that is working fine:
$('#add-block').click(function(e) {
var html_to_add = '<input type="text" placeholder="Your Test" class="form-control" name="we2_test" id="we2_test">';
html_to_add += '<div class="we2_test-input col-md-12 no-pad"></div>';
html_to_add += '<button class="btn btn-default btn-add-test" id="we2_add_test">+</button>';
$(".block-input").append(html_to_add);
event.preventDefault();
});
code to duplicate the field (here is where the page reloads):
$('#we2_add_test').click(function(e) {
event.preventDefault();
$(".we2_test-input").append("<input type=\"text\" placeholder=\"Your Test\" class=\"form-control\" name=\"we3_test\" id=\"we3_test\">");
return false;
});
I already tried this, but it didn't work
1.id="we2_test" need to be class="we2_test" and id=we2_add_test need to be class="we2_add_test",because multiple same id for different HTML element is wrong when you are going to deal them with jQuery
2.Use event delegation:-
Now both code need to be:-
$('#add-block').click(function(e) {
e.preventDefault();
var html_to_add = '<input type="text" placeholder="Your Test we2_test" class="form-control" name="we2_test">';
html_to_add += '<div class="we2_test-input col-md-12 no-pad"></div>';
html_to_add += '<button class="btn btn-default btn-add-test we2_add_test">+</button>';
$(".block-input").append(html_to_add);
});
$(document).on('click','.we2_add_test',function(e) {
e.preventDefault();
$(".we2_test-input").append("<input type='text' placeholder='Your Test' class='form-control we3_test' name='we3_test'>");
});
The first function has event as the function argument, but later on you try to use e.preventDefault(). That doesn't match.
Maybe
$('#add-block').click(function(e) {
var html_to_add = '<input type="text" placeholder="Your Test" class="form-control" name="we2_test" id="we2_test">';
html_to_add += '<div class="we2_test-input col-md-12 no-pad"></div>';
html_to_add += '<button class="btn btn-default btn-add-test" id="we2_add_test">+</button>';
$(".block-input").append(html_to_add);
e.preventDefault();
});
will work? Difficult to say without the complete code though ...
Below is a somehow working version...
This is a little working snippet where I took care of the identity problem and the event delegation as mentioned/solved by #Alive to Die:
$(function(){
$('#add-block').click(function(e) {
var i=$('[name=we2_test]',".block-input").length;
var html_to_add = '<input type="text" placeholder="Your Test" class="form-control" name="we2_test" id="we2_test'+i+'">'
+'<div class="we2_test-input col-md-12 no-pad"></div>'
+'<button class="btn btn-default btn-add-test" id="we2_add_test">+</button>';
$(".block-input").append(html_to_add);
e.stopPropagation();
return false;
});
$('.block-input')
.on('click','#we2_add_test',function(e) {
e.preventDefault();
var j=$('[name=we3_test]',".we2_test-input").length;
$(this).prev().append('<input type="text" placeholder="Your Test" class="form-control" name="we3_test" id="we3_test'+j+'">');
return false;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
add block
<div class="block-input"></div>
Edit:
I replaced $(".we2_test-input").append(...) by $(this).prev().append(...) to ensure that only the div before the button gets added to.
Related
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>
I'm building a multipage form. On a few of the form's pages, I have questions that allow the user to add inputs dynamically if they need to add a job, or an award, etcetera. Here's what I'd like to do/what I have done so far.
What I Want to Do:
As the user adds fields dynamically, I want to validate those fields to make sure they have been filled in, and they are not just trying to move to the next page of the form with empty inputs.
After all the fields are successfully validated, a "Next" button at the bottom of the page, which up until this point was disabled, will become reenabled.
What I know How To Do
With some help, I've been able to workout a validation pattern for the inputs that are not dynamically added (such as First Name, Last Name) and I can extend this same logic to the first set of inputs that are not added dynamically. I have also worked out how to re-enable the "Next" button once all fields are good.
What I do Not Know How To Do
How do I write a function that extends the logic of the simple validation test to also check for dynamically added iterations.
http://codepen.io/theodore_steiner/pen/gwKAQX
var i = 0;
function addJob()
{
//if(i <= 1)
//{
i++;
var div = document.createElement("div");
div.innerHTML = '<input type="text" class="three-lines" placeholder="School Board" name="schoolBoard_'+i+'"> <input type="text" class="three-lines" placeholder="Position" name="position_'+i+'"> <input type="date" class="three-lines" name="years_'+i+'"> <input type="button" value="-" onclick="removeJob(this)">';
document.getElementById("employmentHistory").appendChild(div);
//}
}
function removeJob(div)
{
document.getElementById("employmentHistory").removeChild(div.parentNode);
i--;
};
function checkPage2()
{
var schoolBoard_1 = document.getElementById("schoolBoard_1").value;
if(!schoolBoard_1.match(/^[a-zA-Z]*$/))
{
console.log("something is wrong");
}
else
{
console.log("Working");
}
};
<div id="page2-content">
<div class="input-group" id="previousTeachingExperience">
<p class="subtitleDirection">Please list in chronological order, beginning with your most recent, any and all full-time or part-time teaching positions you have held.</p>
<div class="clearFix"></div>
<label id="teachingExpierience">Teaching Experience *</label>
<div id="employmentHistory">
<input type="text" class="three-lines" name="schoolBoard_1" id="schoolBoard_1" placeholder="School Board" onblur="this.placeholder='School Board'" onfocus="this.placeholder=''" onkeyup="checkPage2()" />
<input type="text" class="three-lines" name="position_1" placeholder="Position" onblur="this.placeholder='Position'" onfocus="this.placeholder=''" onkeyup="checkPage2()" />
<input type="date" class="three-lines" name="years_1" />
<input type="button" name="myButton" onclick="addJob()" value="+" />
</div>
</div><!--end of previousTeachingExperience Div -->
Instead of trying to validate each individual input element, I would recommend trying to validate them all at once. I believe that is what your checkPage2 function is doing.
You can add the onBlur event handler or the onKeyUp event handler you are currently using to all added inputs to run your form wide validation. This has the effect of checking each individual form element if it is valid so you know for sure you can enable the submit button.
Lastly, when removeJob is called, you should also run the form wide validation. It would look something like this:
function addJob()
{
i++;
var div = document.createElement("div");
div.innerHTML = '<input type="text" class="three-lines" placeholder="School Board" name="schoolBoard_'+i+'" onkeyup="checkPage2()"> <input type="text" class="three-lines" placeholder="Position" name="position_'+i+'" onkeyup="checkPage2()"> <input type="date" class="three-lines" name="years_'+i+'" onkeyup="checkPage2()"> <input type="button" value="-" onclick="removeJob(this)">';
document.getElementById("employmentHistory").appendChild(div);
}
function removeJob(div)
{
document.getElementById("employmentHistory").removeChild(div.parentNode);
i--;
checkPage2();
};
For every element that you make with document.createElement(...), you can bind to the onchange event of the input element, and then perform your validation.
Here's an updated version of your CodePen.
For example:
HTML
<div id="container">
</div>
Javascript
var container = document.getElementById("container");
var inputElement = document.createElement("input");
inputElement.type = "text";
inputElement.onchange = function(e){
console.log("Do validation!");
};
container.appendChild(inputElement);
In this case I'm directly creating the input element so I have access to its onchange property, but you can easily also create a wrapping div and append the inputElement to that.
Note: Depending on the freqency in which you want the validation to fire, you could bind to the keyup event instead, which fires every time the user releases a key while typing in the box, IE:
inputElement.addEventListener("keyup", function(e){
console.log("Do validation!");
});
I am attempting to use jQuery to add the dynamic form elements to my page. At the moment I can get one of my form elements to be added when the user clicks the button but the second element isn't being added alongside it.
I do this by appending some html to divs with a specific class when a button is clicked.
I have created a JSfiddle. As you can see the 'ingredient' part is working, however the quantities is not.
https://jsfiddle.net/fe0t3by2/
$('.recipe-ingredients #addNewIngredient').on('click', function () {
var i = $('.recipe-ingredients .ingredient').size() + 1;
$('<div class="form-group ingredient"><label class="control-label" for="searchinput">Ingredients</label><div><input id="ingredient_' + i + '" name="ingredients[]" type="text" placeholder="Ingredients" class="form-control input-md"></div></div>Add Ingredient</div>').appendTo($('.recipe-ingredients .ingredients'));
$('<div class="form-group"><label class="control-label" for="buttondropdown">Quantity</label><div class="input-group"><input id="quantity_' + i + '" name="quantity[]" class="form-control" placeholder="Quantity" type="text"><div class="input-group-btn"><button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">Measure<span class="caret"></span></button><ul class="dropdown pull-right"><li>Grams</li><li>Ounces</li><li>Option three</li></ul></div></div>').appendTo($('.recipe-quantities .quantities'));
});
Thank you
You have misspelled the 'recipe-quantities' class on your quantities div.
<div class="col-md-6 recipe-quantites">
changed to
<div class="col-md-6 recipe-quantities">
At the moment I can get one of my form elements to be added when the user clicks the button but the second element isn't being added alongside it.
With dynamically added content you should delegate the click to the document for example (something where the object is contained in).
jQuery documentation .on()
$(document).on('click', '.recipe-ingredients #addNewIngredient', function () {
JSFiddle demo
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();
});
I have a p element which I want to replace with an input element when user clicks on it. The might not be present during page load so I use delegate to catch the click event.
html(after <p> was loaded)
<div class="phrases">
<div class="predefined-phrase>
<p id="1">A predefined phrase"</p>
</div>
</div>
I want it to be like this
<div class="phrases">
<div class="predefined-phrase">
<input type="text" id="1" class="form-control input-sm" value="A predefined phrase">
</div>
</div>
My js file has the following code:
$(".phrases").on('click', ".predefined-phrase", function (event){
event.preventDefault();
var phrase = $(this).children().text();
var id = $(this).children().attr('id');
var input = '<input type="text" class="form-control input-sm" id="'+id+'" value="'+phrase+'">';
$(this).children().remove();
$(this).append(input);
});
<p> is replaced normally by input but i cannot type anything. I can only type if left click is pressed on input box continiously. I also want to catch a keypress event on the new input so to edit or to delete the specific phrase. But I cannot even type on the input box. Why is this happening? Can i normally catch the keypress event after I have appended the input (and works as it should) inside the click event callback? The point is that after user presses the phrase is edited with ajax and the input box dissappears and p is loaded back with the new edited phrase or fully deleted.
$(function(){
$('.predefined-phrase p').click(function() {
var id = $(this).attr('id');
var phrase = $(this).text();
var newInput="<input type='text' id='"+id+"' value='"+phrase+"' />";
$(this).replaceWith(newInput);
});
});
DEMO FIDDLE
Just check the target. If it is a input, do nothing :
$(".phrases").on('click', ".predefined-phrase", function (event){
if($(event.target).is('input')) return;
event.preventDefault();
var phrase = $(this).children().text();
var id = $(this).children().attr('id');
var input = '<input type="text" class="form-control input-sm" id="'+id+'" value="'+phrase+'">';
$(this).children().remove();
$(this).append(input);
});
Well, this is a native JS solution, but hopefully it will point you in the right direction, or if you an use it instead of jQuery, that works too. Not that I've changed your ID to not start with a number, as mentioned by C-link, as that is not allowed.
document.getElementById("n1").addEventListener("click", function filler(){
this.outerHTML = '<input type="text" id="' + this.id + '" class="form-control input-sm" value="' + this.innerHTML + '" />
this.removeEventListener("click" filler)'
});
I would suggest the next changes:
<div class="predefined-phrase">
<input type="text" data-id="1" class="form-control input-sm" value="A predefined phrase">
</div>
jQuery script:
$('.predefined-phrase').click(function() {
var id = $('p', this).attr('data-id');
var value = $('p', this).text();
$('p', this).replaceWith('<input type="text" data-id="' + id + '" class="form-control input-sm" value="' + value + '" />')
});
First of all, don't use id starting from number.
And for your solution you can use replaceWith method like below:
$('#your_id').replaceWith('<input type="text" id="your_id" class="form-control input-sm" value="A predefined phrase" />');