I'm trying to add the rows dynamically plus auto-increment of a counter.I want to start with 1 then 2 then 3 and so on . I have added my code on plunker ,in which every time the max value is getting in first column like 4 then 1,1,2,3.Where am i going wrong ?i Want it to be 1,2,3,4.
Here is the plunker link http://plnkr.co/edit/GuDbJ3SHOPvWkHfNfd8E?p=preview
var _counter = 0;
function Add() {
_counter++;
var oClone = document.getElementById("template").cloneNode(true);
oClone.id += (_counter + "");
document.getElementById("placeholder1").appendChild(oClone);
document.getElementById("myVal").value=_counter;
}
<div id="placeholder1">
<div id="template">
<div>
Value:<input type="text" id="myVal" placeholder="1">
Quantity:<input type="text" placeholder="Qty">
<input type="button" onClick="Add()" value="Click! ">
</div>
</div>
I think it is because you have multiple divs with the id="myVal". The id attribute should be unique on the page. If not, your page will still load, but you may have unexpected behavior.
You are changing the id of the template div, but not the myVal div.
I assume you are looking for something like this:
var _counter = 0;
function Add() {
_counter++;
var oClone = document.getElementById("template").cloneNode(true);
oClone.id += (_counter + "");
document.getElementById("placeholder1").appendChild(oClone);
oClone.getElementsByClassName("myVal")[0].value = _counter;
}
<div id="placeholder1">
<div id="template">
<div>
Value:
<input type="text" class="myVal" placeholder="1">Quantity:
<input type="text" placeholder="Qty">
<input type="button" onClick="Add()" value="Click! ">
</div>
</div>
</div>
In your original you are cloning your template with the same id for the input. So when you do document.getElementById("myVal").value=_counter;, you only get the first input. I changed it to use class instead and get the input with the appropriate class that is a child of the cloned node.
Related
I am using jQuery to add and remove table rows for a collection of forms within another form in Symfony 4. This was not easy, but eventually made it work. With a macro in Twig I can get this rendered result:
<table>
<div id="document-list" data-prototype="
<tr>
<td>
<fieldset class="form-group">
<div id="program_programDocument___name__" novalidate="novalidate">
<div class="form-group"><input type="text" id="program_programDocument___name___name" name="program[programDocument][__name__][name]" required="required" class="form-control"/>
</div>
</div>
</fieldset>
</td>
<td>
<button type="button"class="remove-collection-widget"data-list="#remove-collection-widget">Remove</button>
</td>
</tr>" data-widget-tags="<div></div>">
</div>
</table>
<button type="button" class="add-another-collection-widget" data-list="#document-list">Add document</button>
I cleaned up this code as much as possible to make it readable. All the HTML within data-prototype="...." is how it should be. My code works (ish) together with some jQuery:
jQuery('.add-another-collection-widget').click(function(e) {
var list = jQuery(jQuery(this).attr('data-list'));
// Try to find the counter of the list or use the length of the list
var counter = list.data('widget-counter') | list.children().length;
// grab the prototype template
var newWidget = list.attr('data-prototype');
// replace the "__name__" used in the id and name of the prototype
// with a number that's unique to your emails
// end name attribute looks like name="contact[emails][2]"
newWidget = newWidget.replace(/__name__/g, counter);
// Increase the counter
counter++;
// And store it, the length cannot be used if deleting widgets is allowed
list.data('widget-counter', counter);
// create a new list element and add it to the list
var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget);
newElem.appendTo(list);
});
$(function() {
$(document).on("click", ".remove-collection-widget", function() {
$(this).closest("tr").remove();
});
});
The problem is, the rendered result when added more form rows is that they don't actually end up within the table. You can see for yourself (JSFiddle) the result looks alright, but in reality it's not.
I am pretty sure it has to do with my jQuery, but I am stuck now and hope some of you can point out what is wrong.
Putting a div as a direct child of a table isn't proper HTML, which is what's tripping it up.
Move id="document-list" data-prototype="... to table element
Get rid of div inside table
Change data-widget-tags to tr instead of div
Remove wrapping tr from data-prototype
Solution
jQuery('.add-another-collection-widget').click(function(e) {
var list = jQuery(jQuery(this).attr('data-list'));
var counter = list.data('widget-counter') | list.children().length;
var newWidget = list.attr('data-prototype');
newWidget = newWidget.replace(/__name__/g, counter);
counter++;
list.data('widget-counter', counter);
var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget);
newElem.appendTo(list);
});
$(function() {
$(document).on("click", ".remove-collection-widget", function() {
$(this).closest("tr").remove();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="document-list" data-prototype="
<td>
<fieldset class="form-group">
<div id="program_programDocument___name__" novalidate="novalidate">
<div class="form-group"><input type="text" id="program_programDocument___name___name" name="program[programDocument][__name__][name]" required="required" class="form-control"/>
</div>
</div>
</fieldset>
</td>
<td>
<button type="button"class="remove-collection-widget"data-list="#remove-collection-widget">Remove</button>
</td>" data-widget-tags="<tr></tr>">
</table>
<button type="button" class="add-another-collection-widget" data-list="#document-list">Add document</button>
Documentation
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table (see Permitted Content)
function js() {
document.getElementById("example").innerHTML = document.getElementById("example").innerHTML+"<input type=\"text\" name=\"name\" />";
}
<div id="example">
<input type="text" name="name[]" />
</div>
<button type="button" onclick="js();">Click</button>
I have a form, which need variable number of input types.
<form action="" method="">
[...]
<div id="mezok">
<div id="input_id">
<input type="text" name="name" />
</div>
</div>
[...]
</form>
I add and remove further inputs (along with their divs!) via an ajax call. Javascript calls a php which generates a new input_id div, and then concatenates to the rest of the div id="mezok". Adding and removing inputs are fine as long as everything is empty. However, when I add a new div when there is something in the input, it clears the rest of the inputs.
document.getElementById("mezok").innerHTML = document.getElementById("mezok").innerHTML+http.responseText;
document.getElementById("mezok").innerHTML += http.responseText;
document.getElementById("mezok").innerHTML.concat(http.responseText);
(The last one is not working at all...)
TL;DR: concat input to input, values of inputs disappear. :'(
Don't use innerHTML. What you are doing is redrawing the entire container contents, deleting existent inputs and creating new inputs each time. My experience says that when you are accessing innerHTML, recheck your code as you are probably doing something weird.
What you have to do is to create inputs individually and append them to the container, without touching the rest of the inputs. Is like appending elements to an array.
This way the code is more self-explanatory, and better, is way more performant:
function js() {
var input = document.createElement("input"); // Create a new input element. Is like "<input>".
input.setAttribute("type", "text"); // Set the 'type' attribute to 'text'. Is like having '<input type="text">'
input.setAttribute("name", "name[]"); // Set the 'name' attribute to 'name[]'. Is like having '<input name="name[]">' but because you already have set the type, now is like having '<input type="text" name="name[]">'
document.getElementById("example").appendChild(input); // Push it to the container
}
<div id="example">
<input type="text" name="name[]" />
</div>
<button type="button" onclick="js();">Click</button>
The code below could be a solution for you. In this way you're not going to overwrite the existing inputs with the associated values while you're adding new inputs.
function js() {
var inputElementToAppend = document.createElement('input');
inputElementToAppend.innerHTML = "<input type=\"text\" name=\"name\" />";
document.getElementById("example").appendChild(inputElementToAppend.firstChild);
}
<div id="example">
<input type="text" name="name[]" />
</div>
<button type="button" onclick="js();">Click</button>
Let me know if this worked for you.
Following working fine for me.
<button onclick="myFunction()">Try it</button>
<p id="demo">ABC</p>
<script>
function myFunction() {
var x = document.getElementById("myP").innerHTML;
document.getElementById("demo").innerHTML += `<input type=\"text\" name=\"name\" />`;
}
<script>
I would recommend to use appendChild and removeChild instead of innerHTML
I want to be able to display the same piece of html code 10 times under the div called: <div id="add_remove_product_name"> By clicking on the button called: <button id="add_another_product_name">. I think I need some kind of a for loop for the job but are not sure. Any suggestion will be helpful, thanks.
My HTML code:
<div id="product_name">
<input id="skriv_produktnavn" placeholder="Skriv Produktnavn her" required></label>
<button id="add_another_product_name">Tilføj endnu et produktnavn</button>
<div id="add_remove_product_name">
<input id="added_product_name" placeholder="Skriv Produktnavn her" required></label>
<button id="remove_product_name">X</button>
</div>
Use a for loop to concatenate 10 copies of the HTML code. Then use .after() to put this after the DIV.
$("#add_another_product_name").click(function() {
var html = '';
for (var i = 0; i < 10; i++) {
html += 'html code that you want to repeat';
}
$("#add_remove_product_name").after(html);
}
You can use jQuery clone() however when cloning an element all the attributes will be the same. Fo example they will all have the same id attribute which will cause problems and it is not valid html
So in order to do the clone correctly you have fix the cloned element
DEMO: http://jsfiddle.net/rpyt445e/
var $tpl = $('#product_name').clone();
var num = 0
$('#clone').click(function () {
num++;
var $cloned = $tpl.clone();
$cloned.attr('id', $tpl.attr('id') + '_' + num);
$(':not([id=""])', $cloned).each(function(){
$(this).attr('id', $(this).attr('id') + '_'+num);
});
$cloned.appendTo('#wrapper');
});
HTML:
<div id="wrapper">
<div id="product_name">
<input id="skriv_produktnavn" placeholder="Skriv Produktnavn her" required />
<button id="add_another_product_name">Tilføj endnu et produktnavn</button>
<div id="add_remove_product_name">
<input id="added_product_name" placeholder="Skriv Produktnavn her" required />
<button id="remove_product_name">X</button>
</div>
</div>
</div>
<button id="clone">Clone</button>
A technique for adding the additional elements without having to create ugly strings of html in the JavaScript is to start with one hidden set of the elements in the html. At page load time, you remove that set, but keep a reference to it. Then when you want to add a set to the page, you clone the set you removed. All of this is easier if you add a container div around the additional inputs.
You also need to make sure id attribute values are unique. In the case of the remove buttons, you can replace the id with a class. As for the input id values, if you really need them, you can add an index value to them.
Since the remove buttons are dynamically added, I suggest using event delegation when binding the click-handler.
HTML:
<div id="product_name">
<input id="skriv_produktnavn" placeholder="Skriv Produktnavn her" required="required"/>
<button id="add_another_product_name">Tilføj endnu et produktnavn</button>
<div id="additional_product_names">
<div class="add_remove_product_name" style="display: none;">
<input id="added_product_name" placeholder="Skriv Produktnavn her" required="required"/>
<button class="remove_product_name">X</button>
</div>
</div>
</div>
JavaScript:
$(function() {
var MAX = 10;
var $addBtn = $('#add_another_product_name'),
$additionalContainer = $('#additional_product_names');
$TEMPLATE = $additionalContainer.children(':first').remove();
function update() {
var $additonalDivs = $additionalContainer.children();
// Enable/disable the add button.
$addBtn.prop('disabled', $additonalDivs.length >= MAX);
// Re-index the "id" attributes.
$additonalDivs.find('input').attr('id', function(i) {
return 'added_product_name[' + i + ']';
});
}
$addBtn.click(function() {
$TEMPLATE.clone().appendTo($additionalContainer).show();
update();
});
$('#product_name').on('click', '.remove_product_name', function() {
$(this).closest('.add_remove_product_name').remove();
update();
});
});
jsfiddle
Hi all I have a form in which I dynamically add in a new row consisting of a text box and check button on button press. However I need some sort of way to know which checkbuttons were pressed in the post data and therefore need a value field consisting of an ID on each of the the check buttons, code is seen below:
<div id='1'>
<div class="template">
<div>
<label class="right inline">Response:</label>
</div>
<div>
<input type="text" name="responseText[]" value="" maxlength="400" />
</div>
<div>
<input type="radio" name="responseRadio[]" value="" />
</div>
</div>
<div>
<input type="button" name="addNewRow" value="Add Row" />
</div>
</div>
JS to add new row:
var $template = $('.template');
$('input[type=button]').click(function() {
$template.clone().insertAfter($template);
});
can anyone suggest a good way to help me know in the post data which text field, links to which check button, and to know if it was pressed?
at the moment if you were to add 3 rows and check row 3 I have no way of identifying that row three was the button pressed - This is my issue
after you cloned it, change the name so you know about this input
also it's good to have a counter for naming:
like : 'somename[myInput' + counter + ']'
update:
var counter = 0;
var $template = $('.template');
$('input[type=button]').click(function() {
counter++;
$template.clone().attr('name' , 'somename[myInput' + counter + ']').insertAfter($template);
});
now you have array named:somename which you can have a loop over its content on your form handler.
I am trying to clone and insert items in order in JS, I can clone and add elements but the order seems to be incorrect, I am trying to assign a value to the radio buttons so I can tie the radio buttons to the text fields as seen below:
<div id='1'>
<div class="template">
<div>
<label class="right inline">Response:</label>
</div>
<div>
<input type="text" name="responseText[]" value="" maxlength="400" />
</div>
<div>
<input type="checkbox" name="responsCheck[]" value="0" />
</div>
</div>
<div>
<input type="button" name="addNewRow" value="Add Row" />
</div>
</div>
JS:
var $counter = 0;
var $template = $('.template');
$('input[type=button]').click(function() {
var $elem = $template.clone();
$elem.find("input:text").val("");
$copy.find("input:radio").val($counter);
$elem.insertAfter($template);
});
If I add three rows for example, the Values of the checkbuttons are in the following order:
0
2
1
I need the Values to be in the following order:
0
1
2
anybody got any ideas? I think it must be the way I am inserting the clone? When I am using radio buttons this line seems to work:
$elem.insertAfter($('#1 .clone').last());
but when using checkboxes it doesn't seem to work any ideas?
To me problem looks like that on adding second entry $template still points to the first entry.
I would try by moving $template initialization inside click handler and changing it like below.
var $counter = 0;
$('input[type=button]').click(function() {
var $template = $('.template:last');
});
This way $template should point to the last template inserted and it should work as expected.
Maybe you need to use:
$("#1").append($elem);
instead
$elem.insertAfter($template);
Or select the last every time.
var $template = $('.template').last();
Put them into a js array and sort them by val:
function SortByValue(elem1, elem2){
var e1 = Number($(elem1).val());
var e2 = Number($(elem2).val());
return ((e1 < e2) ? -1 : ((e1 > e2) ? 1 : 0));
}
var sortedValues = $.makeArray($(jQSelector)).sort(SortByValue);
Here is a fiddle