Dynamically created DOM manipulation button not firing event - javascript

I have a function to add and remove a field but the remove function doesnt work somehow.
HTML:
<div id="parts">
Part
<input type="text" id="auto_part" name="auto_part" />
<br />
Description
<input type="text" id="auto_description" name="auto_description" />
<br />
</div>
Add another part
jQuery:
$(function() {
var scntDiv = $('#parts');
var i = $('#parts input').size();
$('#addField').on('click', function() {
$('<br /><div id="parts"><span>Part</span> <input type="text" id="auto_part'+i+'" name="auto_part'+i+'" /><br />').appendTo(scntDiv);
$('<span>Description</span> <input type="text" id="auto_description'+i+'" name="auto_description'+i+'" /> <br />').appendTo(scntDiv);
$('<input type="hidden" id="row_count" name="row_count" value="" />').appendTo(scntDiv);
$('Remove</div>').appendTo(scntDiv);
i++;
return false;
});
$('#removefield').on('click', function() {
if( i > 2 ) {
$(this).parents('div').remove();
i--;
}
return false;
});
});
The problem must have to do with this line:
$('#removefield').on('click', function() {
It doesnt pass that condition.
When I click on Remove it doesnt do anything at all it just scrolls to the top.

You are binding the click handler to the elements that are present in the DOM. But, your #removefield element is being dynamically added. So, the event handler is not attached to it.
You can use .on() to use event delegation and handle also future elements. Also, you may want to use classnames instead of and id attributes. id attributes need to be unique, but you can set the classname to as many elements as you want.
Remove
$("#parts").on("click", ".removefield", function() {
/* ... */
});
The reason why your "Remove" link doesn't work is because you are adding the dynamic <div> element by parts hence making it invalid markup. You should be adding it all together at once. For example,
$('#addField').on('click', function () {
var part = '<div id="parts' + i + '"><span>Part</span> <input type="text" id="auto_part' + i + '" name="auto_part' + i + '" /><br/>' +
'<span>Description</span> <input type="text" id="auto_description' + i + '" name="auto_description' + i + '" /> <br />' +
'<input type="hidden" id="row_count' + i + '" name="row_count' + i + '" value="" />' +
'Remove</div>';
scntDiv.after(part);
i++;
return false;
});
$(document).on("click", ".removefield", function() {
if( i > 2 ) {
$(this).parent('div').remove();
i--;
}
return false;
});
You can see it here.

try
$('#removefield').live("click", function() {

Related

Create multiple fields on input

I am trying to create multiple fields when I enter a number to tell it how many to create... I have utilised some code that I have written previously but now it's no longer working.
HTML:
<input type="text" name="rows">
jQuery:
$(document).ready(function() {
$('#rows').change(function() {
var rows = $(this).val();
for(i=0;i<=rows;i++) {
$('#form').append('<div><input type="text" name="N' + i + '"></div>');
$('#form').append('<div><select name="S'+ i +'"><option value="Text">Text</option><option value="editor">Editor</option></select></div>');
$('#form').append('<div><input type="text" name="V' + i + '"></div>');
}
}
}
Fiddle: https://jsfiddle.net/dc5665xk/1/
ID attribute is missing for rows element.
There is no form element having form as ID
Syntax error as closing braces were missing.
Note: var keyword was missing in for-loop
$(document).ready(function() {
$('#rows').change(function() {
var rows = $(this).val();
for (var i = 0; i <= rows; i++) {
$('#form').append('<div><input type="text" name="N' + i + '"></div>');
$('#form').append('<div><select name="S' + i + '"><option value="Text">Text</option><option value="editor">Editor</option></select></div>');
$('#form').append('<div><input type="text" name="V' + i + '"></div>');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<form id="form">
<input type="text" name="rows" id="rows">
</form>

How can I call a jquery function on selecting a dropdown option for dynamically created inputs?

So this is what the page looks like currently:
The first one is hardcoded in and then the rest are added/removed by the buttons. The first one can also be added and removed from the buttons. I want to call a jquery function when the dropdown is changed to change the type from textbox/radiobutton (and text)/checkbox (and text) etc.
Currently it only works on the first Question/Answer and only works if it is the original and not dynamically created. I'm not sure why that is.
Here is how the Q/A's are created and removed
$("#addButton").click(function () {
if (counter > max_fields) {
alert("Only " + max_fields + " Questions allowed");
return false;
}
var newTextBoxDiv = $(document.createElement('div'))
.attr("id", 'TextBoxDiv' + counter);
newTextBoxDiv.after().html('<label>Question #' + counter + ' : </label>' +
'<input type="text" name="textbox' + counter +
'" id="questionbox' + counter + '" value="" />' +
' <select id="choice'+ counter +'"><option>Type</option><option>Radio Button</option><option>Text Box</option><option>Check Box</option></select>' +
'<button id = "remove' + counter + '">Remove</button>' +
'<br/><label>Answer #' + counter + ' : </label>' +
'<div id="Answers' + counter + '">' +
'Option 1: <input type="text" id="answerbox' + counter +
'1" name="answerbox' + counter + '" value="" />' +
'<br/>Option 2: <input type="text" id="answerbox' + counter +
'2" name="answerbox' + counter + '" value="" />' +
'<br/>Option 3: <input type="text" id="answerbox' + counter +
'3" name="answerbox' + counter + '" value="" />' +
'<br/>Option 4: <input type="text" id="answerbox' + counter +
'4" name="answerbox' + counter + '" value="" /></div>');
newTextBoxDiv.appendTo("#TextBoxesGroup");
counter++;
});
$("#removeButton").click(function () {
if (counter == 1) {
alert("No more textbox to remove");
return false;
}
counter--;
$("#TextBoxDiv" + counter).remove();
});
This is how I tried to get it to change types
$('#choice1').change(function () {
var selected_item = $(this).val()
var searchEles = document.getElementById("Answers1").children;
alert(searchEles.length);
for(var i = 0; i < searchEles.length; i++) {
$('#answerbox1' + i).attr('type', selected_item);
//alert(searchEles.length);
}
});
The web page code is as follows
<input type='button' value='Add Question' id='addButton'/>
<input type='button' value='Remove Question' id='removeButton'/>
<div id='TextBoxesGroup'>
<div id="TextBoxDiv1">
<label>Question #1 : </label>
<input type='text' id='questionbox1'/>
<select id="choice1" onchange="$('#choice').val('id');"> //this on change was added and currently does nothing it seems.
<option value="">Type</option>
<option value="radio">Radio Button</option>
<option value="text">Text Box</option>
<option value="checkbox">Check Box</option>
</select>
<button id="remove1">Remove</button>
<br/><label>Answer #1 : </label>
<div id="Answers1">
Option 1: <input type="text" id='answerbox11' name='answerbox1' value="" />
<br/>Option 2: <input type="text" id='answerbox12' name='answerbox1' value="" />
<br/>Option 3: <input type="text" id='answerbox13' name='answerbox1' value="" />
<br/>Option 4: <input type="text" id='answerbox14' name='answerbox1' value="" />
</div>
</div>
</div>
I tried to do something like onchange and then get the ID and go from there but that didn't work. I know it doesn't match the back end jquery name.
TL;DR
I don't know how to dynamically write the jQuery function to work
for all of them.
I don't know why even if I hardcode it to #choice1 it will work
when its first created but not if i remove and add it even though it
has the same exact values. I think it might MAYBE have to do with
for loop, because the alert doesn't even trigger the second time
around.
You could try
$(document).on("change", ".selector", function(){
//do something
});
//Edit
Add to the select element class for example select-option and a tag that will hold the select's counter
//JS
...'<select id="choice'+counter+'" class="select-option" number="'+counter+'">'...
and then your on change function would look something like
$(document).on("change", ".select-option", function(){
//do something
var selected_type = $(this).attr('value');
var ans_number = $(this).attr('number');
$("#answerbox"+ans_number).children('input').attr('type', selected_type);
});
I hope this will help :)
For dynamically added elements use
$(selector).on("change", callback)
If element is dynamic then Jquery will not bind directly as
$('#choice1').change(function (){});
But for that you need to call same function with some static element.
For Ex:
$(".listingDiv").find('#choice1').change(function (){});
or
$(document).find('#choice1').change(function (){});
and it will work. try it.
When elements will be aded dynamically, best practice is to delegate the handler(s). Put your handler on the containing div or window/document
.
First
<select id="choice1" onchange="$('#choice').val('id');"> //this on change was added and currently does nothing it seems.
This is one reason your never be called. If you bind an event listener to an element, you should not write the actual JS code inside the element.
Second
Bind your listener like this:
$('#choice1').on("change", function () {
var selected_item = $(this).val()
var searchEles = document.getElementById("Answers1").children;
alert(searchEles.length);
for(var i = 0; i < searchEles.length; i++) {
$('#answerbox1' + i).attr('type', selected_item);
//alert(searchEles.length);
}
});

Same function for different sections - relative referencing in jquery

By using relative references I am able to remove items which have been added to the list within a specfic part of the form. For example, by adding a requirement it can be deleted just from the requirement.
My issue is two fold:
Adding an item to references adds it to all three categories
When I try to add values to the other sections (qualifications) it says my input was blank.
http://jsfiddle.net/spadez/9sX6X/60/
var container = $('.copies'),
value_src = $('#current'),
maxFields = 10,
currentFields = 1;
$('.form').on('click', '.add', function () {
value_src.focus();
if ($.trim(value_src.val()) != '') {
if (currentFields < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
value_src.focus();
$(this).parents('.line').remove();
currentFields--;
});
Is it possible to modify this code without repeating it for each section, by using relatively references such as "parent" for example. I want to use this same script for all three sections but have it so each list is independant.
I'm new to javascript so I was wondering if this is possible because I only managed to get it working on the delete.
You have to use this to get the current element. In your case this refers to the button which was clicked.
The next step is to get the input box which belongs to the button. E.g. $(this).prev(); like in this example:
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
http://jsfiddle.net/9sX6X/62/
The same is also true for your appending part. Your are appending your html to all three elements which match $('.copies'). Instead you have to try to get there from this.
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var copies = $(this).parent().prev();
http://jsfiddle.net/9sX6X/63/
I would suggest adding a wrapping div to each section.
<div class="section">
<h4>Requirements</h4>
<div class="copies"></div>
<div class="line">
<input id="current" type="text" name="content" placeholder="Requirement" />
<input type="button" value="Add" class="add" />
</div>
</div>
Then you can do this:
var $section = $(this).closest(".section");
$(html).appendTo($section.find(".copies"));
This will add to just the related .copies element instead of to all .copies as your code does now. A similar approach can be used for all other elements as well.

Add (and remove) group of textelements dynamically from a web form using javascript/jquery

im very new at javascipt (im php developer) so im really confused trying to get this working.
In my web form i have 3 textfields (name, description and year) that i need to let the user add as many he needs, clicking on a web link, also, any new group of text fields need to have a new link on the side for removing it (remove me).
I tried some tutorial and some similar questions on stackoverflow but i dont get it well. If you can show me a code example just with this function i may understand the principle. Thanks for any help!
this is the simplest thing that has come to my mind, you can use it as a starting point:
HTML
<div class='container'>
Name<input type='text' name='name[]'>
Year<input type='text' name='year[]'>
Description<input type='text' name='description[]'>
</div>
<button id='add'>Add</button>
<button id='remove'>Remove</button>
jQuery
function checkRemove() {
if ($('div.container').length == 1) {
$('#remove').hide();
} else {
$('#remove').show();
}
};
$(document).ready(function() {
checkRemove()
$('#add').click(function() {
$('div.container:last').after($('div.container:first').clone());
checkRemove();
});
$('#remove').click(function() {
$('div.container:last').remove();
checkRemove();
});
});
fiddle here: http://jsfiddle.net/Fc3ET/
In this way you take advantage of the fact that in PHP you can post arrays: server side you just have to iterate on $_POST['name'] to access the various submissions
EDIT - the following code is a different twist: you have a remove button for each group:
$(document).ready(function() {
var removeButton = "<button id='remove'>Remove</button>";
$('#add').click(function() {
$('div.container:last').after($('div.container:first').clone());
$('div.container:last').append(removeButton);
});
$('#remove').live('click', function() {
$(this).closest('div.container').remove();
});
});
Fiddle http://jsfiddle.net/Fc3ET/2/
jsFidde using append and live
String.format = function() {
var s = arguments[0];
for (var i = 0; i < arguments.length - 1; i++) {
var reg = new RegExp("\\{" + i + "\\}", "gm");
s = s.replace(reg, arguments[i + 1]);
}
return s;
}
var html = "<div>" + '<input name="name{0}" type="text" />' + '<input name="description{1}" type="text" />' + '<input name="year{2}" type="text" />' + '<input type="button" value="remove" class="remove" />' + '</div>',
index = 0;
$(document).ready(function() {
$('.adder').click(function() {
addElements();
})
addElements();
$('.remove').live('click', function() {
$(this).parent().remove();
})
});
function addElements() {
$('#content').append(String.format(html, index, index, index));
index = index + 1;
}
Look at this: http://jsfiddle.net/MkCtV/8/ (updated)
The only thing to remember, though, is that all your cloned form fields will have the same names. However, you can split those up and iterate through them server-side.
JavaScript:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$("#addnew").click(function(e) {
$("#firstrow").clone() // copy the #firstrow
.removeAttr("id") // remove the duplicate ID
.append('<a class="remover" href="#">Remove</a>') // add a "remove" link
.insertAfter("#firstrow"); // add to the form
e.preventDefault();
});
$(".remover").live("click",function(e) {
// .live() acts on .removers that aren't created yet
$(this).parent().remove(); // remove the parent div
e.preventDefault();
});
});
</script>
HTML:
Add New Row
<form id="myform">
<div id="firstrow">
Name: <input type="text" name="name[]" size="5">
Year: <input type="text" name="year[]" size="4">
Description: <input type="text" name="desc[]" size="6">
</div>
<div>
<input type="submit">
</div>
</form>
Try enclosing them in a div element and then you can just remove the entire div.
Try this
Markup
<div class="inputFields">
..All the input fields here
</div>
Add
<div class="additionalFields">
</div>
JS
$("#add").click(function(){
var $clone = $(".inputFields").clone(true);
$clone.append($("<span>Remove</span").click(functio(){
$(this).closest(".inputFields").remove();
}));
$(".additionalFields").append($clone);
});
There are 2 plugins you may consider:
jQuery Repeater
jquery.repeatable
This question has been posted almost 4 years ago. I just provide the info in case someone needs it.

Element is not defined jQuery $(element).remove()

I have this JavaScript that adds a form field, along with a link to remove that field:
var fieldCount = 0;
function addField() {
var name = 'file' + fieldCount;
var row = 'row' + fieldCount;
var str = '<p id="' + row + '"><label for="' + name + '">File to upload: <input type="file" name="' + name + '" id="' + name + '" />(100MB max size) <a onclick="removeRow(' + row + '); return false;">[-]</a></label></p>';
fieldCount++;
$("#fields").append(str);
};
function removeRow(id) {
$(id).remove();
};
Here is the markup:
<form id="ajaxUploadForm" action="<%= Url.Action("AjaxUpload", "Upload")%>" method="post" enctype="multipart/form-data">
<fieldset id="uploadFields">
<legend>Upload a file</legend>
<div id="fields"></div>
<input id="ajaxUploadButton" type="submit" value="Submit" />
</fieldset>
<a onclick="addField(); return false;" id="add">Add</a>
<div id="resultBox">
<p id="status" style="margin:10px;"></p>
</div>
</form>
The addFields works as expected, but when I click the remove link firebug tells me that row# is not defined, where # is any number of the added fields.
Any help would be appreciated!
You need to pass a valid selector expression for an ID selector (#ID), either in the removeRow call (also note the quotes surrounding the ID selector):
'<a onclick="removeRow(\'#' + row + '\'); return false;">'
Or in the removeRow function itself:
function removeRow(id) {
$("#" + id).remove();
};
You need to have quotes around it, since it's a string.
You also need the "#" to make it into a selector:
var str = '... <a onclick="removeRow(\'#' + row + '\'); return false;">...';
A better way would be to assign the onclick as a function (not sure of the jQuery way to do this but in plain Javascript):
var a = document.createElement('a');
a.onclick = (function(row)
{
return function()
{
removeRow(row);
return false;
};
})();
You are passing in the string value of row12, but the selector should be:
$('#'+row).remove()
The # specifies that you are looking for an ID. I agree with what I think one of the other answers was about to say, you should just use the onclick events natural this keyword instead:
<p onclick="remove(this)">something</p>
function remove(what) {
$(what).remove()
}
Or, maybe just forget the whole thing all together and switch to behavior for those kinds of rows:
$('.removableRow').live('click', function() {$(this).remove()});
Then you just specify that the row is removable, and never have to worry about binding events at all:
<p><a class="removableRow" href="#">Remove</a></p>

Categories