Select dynamically created element - javascript

I created a div dynamically and attached to div. I'm trying to add data from query and load it to that text field. But, I'm unable to select the dynamically created elements because its not visible in the DOM, since its already loaded.
This is what I have fiddle
<div id="parent">
<input id='childButton' type="button" value="Add"/>
<div id="child" data-row="0">
<input type="text" value="" />
</div>
</div>
var rowNum = 0;
$('#parent').on('click', '#childButton', function() {
var clone = $('#child').clone().attr('data-row', ++rowNum);
$('#parent').append(clone);
console.log($('#child[data-row=1]').length);
});

The problem is the id selector, will return only the first element with the given id. In your case you are creating multiple elements with the id child. So #child will return the first child element, but then applying the data-row rule will filter out the selected element so you are getting 0 are the result.
The solution is to use a class instead of id to select the element
var rowNum = 0;
$('#parent').on('click', '#childButton', function() {
var clone = $('#child').clone().attr('data-row', ++rowNum).removeAttr('id');
$('#parent').append(clone);
//here clone refers to the dynamically create element
//but if you want to fetch the element using a selector then
snippet.log($('.child[data-row=1]').length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<div id="parent">
<input id='childButton' type="button" value="Add" />
<div id="child" class="child" data-row="0">
<input type="text" value="" />
</div>
</div>

You're cloned element with same id, if you want to check just use
console.log($('div[data-row=1]').length);
Like others said, an ids should be unique. Use class definition instead for child id name.

When you're cloning an element with id, change the id (fiddle):
var rowNum = 0;
$('#parent').on('click', '#childButton', function() {
var origin = $('#child');
var originId = $('#child').attr('id');
var cloneId = originId + rowNum;
var clone = $('#child').clone().attr('data-row', ++rowNum).attr('id', cloneId);
$('#parent').append(clone);
console.log($('#' + cloneId).length);
});

DEMO
var rowNum = 0;
$('#parent').on('click', '#childButton', function() {
var clone = $('#child').clone().attr('data-row', ++rowNum);
$('#parent').append(clone);
console.log($('#parent input:text').length);
});
You can also select the input by using the selector input:text
UPDATE
DEMO
IF you want to select the specific input to set value into you can use the index and set the value by finding that index

I think your selector is wrong it must be:
console.log($('#child[data-row="1"]').length);
and consider to remove the id attr in order to avoid multiple ids.
Demo: http://jsfiddle.net/o1j7z1gL/

Related

JavaScript- dynamically adding input to a page

i am using JavaScript to add a div on the fly. The div should contain a form input whose 'name' attribute WILL changes in value incrementally.
I have managed to do this- I however have two problems.
First Problem:
The first div that i created is cancelled out by the next dynamically created div.
thus, when i submit the form, the first dynamically created imput form is blank-
but subsequent ones have values on them.
MY CODE :
html
<div id="dynamicDivSection"></div>
<button id="addbutton">add box</button>
<div id="boxes">
<div class="box">
<input type="text" id='dynamic-imput' name="">
</div>
</div>
javascript
var addbutton = document.getElementById("addbutton");
var key = 1;
addbutton.addEventListener("click", function() {
key++;
document.getElementById('dynamic-imput').name = 'ser['+key+'][\'name\']';
var boxes = document.getElementById("boxes");
var head = document.getElementById("dynamicDivSection");
var clone = boxes.firstElementChild.cloneNode(true);
head.appendChild(clone);
});
i suspect that the problem is causing by this:
document.getElementById('dynamic-imput').name =
'ser['+key+'][\'name\']';
i.e when i create the dynamic div it creates several inputs on the page that contain the same Id. if i am correct, then perhaps teh solution is to change the Id of the newly created imput - however, i am not sure how to change the Id of a dynamically created Imput.
Second problem.
i want each dynamically created div to go to the top of the page; i.e to be placed before the earlier created dynamic div- however, at the moment each dynamically created div go directly under the first dynamically created div.
You can insert as the first child with:
parent.insertAdjacentElement('afterbegin', nodeToInsert);
You can get and set attributes such as id with setAttribute and getAttribute. Though I'm not sure why you even need an ID here, it would be simpler not to have one and select the element with a class.
var addbutton = document.getElementById("addbutton");
var key = 1;
addbutton.addEventListener("click", function() {
key++;
document.getElementById('dynamic-imput').name = 'ser['+key+'][\'name\']';
var boxes = document.getElementById("boxes");
var head = document.getElementById("dynamicDivSection");
var clone = boxes.firstElementChild.cloneNode(true);
var clonedInput = clone.firstElementChild;
clonedInput.setAttribute('id', clonedInput.getAttribute('id') + '-' + head.children.length);
head.insertAdjacentElement('afterbegin', clone);
});
<div id="dynamicDivSection"></div>
<button id="addbutton">add box</button>
<div id="boxes">
<div class="box">
<input type="text" id='dynamic-imput' name="">
</div>
</div>

How to change data-attr when clone div

I have issue with cloning a div.
I have a div with id=director-uploads1. I want to append a div with class=director-uploads-hidden to it. I want to set newly cloned div with class director-uploads-hidden data-number to be with value #director-uploads1 data-number + 1.
$(document).ready(function() {
function clone(){
var number = $('#director-uploads1').attr('data-number');
var director = $('.director-uploads-hidden').html();
var clone = $('#director-uploads1').append(director)
.find("*")
.each(function() {
var name = $(this).attr('name');
})
.on('click', 'button.clone', clone);
//I want to get $("#director-uploads1") attr data-number and to set data-number to the newly cloned div to be current value + 1
//First I did it in this way $("#director-uploads1").attr('data-number', parseInt(number)+1); but I don't want to change initial value of div, only value of the cloned div
}
$("button#add-director").on("click", clone);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="director-uploads number" id="director-uploads1" data-number="0" data-changed="0">
//some data
</div>
<div class="director-uploads-hidden number" style="display:none;" data-number="1" data-changed="0">
//cloned data
</div>
<button type="button" class="btn btn-success" id="add-director">Add Additional Director</button>
So, that after that I pass data to controller via ajax, I can get data-number of each separate div to be different, so that I can differ them.
How could I do that? Thanks.
Updated:
$(document).ready(function() {
function clone(){
var number = $('.director-uploads-hidden').attr('data-number');
var director = $('.director-uploads-hidden').clone(true);
director.data("number", parseInt(number)+1);
$('#director-uploads1').append(director);
director.css("display", "block");
}
$("button#add-director").on("click", clone);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="director-uploads number" id="director-uploads1" data-number="0" data-changed="0">
//some data
</div>
<div class="director-uploads-hidden number" style="display:none;" data-number="1" data-changed="0">
//cloned data
</div>
<button type="button" class="btn btn-success" id="add-director">Add Additional Director</button>
Thank you all for help, maybe it's not the best solution, but I tried with this and it's working:
$(document).ready(function() {
function clone(){
var number = $('#director-uploads1').attr('data-number');
$("#director-uploads1").attr('data-number', parseInt(number)+1);
$('.director-uploads-hidden').find('.app-file').attr('data-item', parseInt(number)+1);
var director = $('.director-uploads-hidden').html();
$('#director-uploads1').append(director)
.find("*")
.each(function() {
var name = $(this).attr('name');
})
.on('click', 'button.clone', clone);
}
$("button#add-director").on("click", clone);
$("html").on('change', '.app-file', function(){
var number = $(this).attr('data-item');
console.log(number);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="director-uploads number" id="director-uploads1" data-number="0" data-changed="0">
<input type="file" class="app-file director_documents" data-item="0" name="director_front_passport[]"/>
</div>
<div class="director-uploads-hidden number" style="display:none;" data-number="1" data-changed="0">
<input type="file" class="app-file director_documents" data-item="0" name="director_front_passport[]"/>
</div>
<button type="button" class="btn btn-success" id="add-director">Add Additional Director</button>
Your clone variable won't be holding a clone of #director-uploads1 it's going to be the collection that find('*') creates.
And $('.director-uploads-hidden').html() will only get the inner html, not the outer div tag that holds the data attribute.
To make a clone you would simply use the clone() jQuery method
var $clone = $('.director-uploads-hidden').clone();
After that to change the data attribute you just set it from $clone not $("#director-uploads1")
$clone.data('number', parseInt(number,10)+1);
//or
$clone.attr('data-number', parseInt(number,10)+1);
Also
.on('click', 'button.clone', clone);
Is trying to set the click handler as your element not your function, because the local variable clone is named the same as your function. Rename your clone variable, for instance like $clone as in the example above.
Try with this snippet.
You can change the attributes and append position as per your need.
//Get old number from the first div
var newNumber = parseInt($('#director-uploads1').attr('data-number'));
$('#add-director').click(function(){
//Get the new length that you would like to set for id
var newLength = parseInt($('.number').length)+1;
//Increment the old number value with +1 to set the new number for every div.
newNumber += 1;
$('div#director-uploads1')
.clone()
.attr('id', 'director-uploads'+newLength)
.attr('data-number', newNumber)
.removeClass()
.addClass('director-uploads-hidden number')
.html('clone data: number'+newNumber +': id '+' director-uploads'+newLength)
.insertBefore('#add-director');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="director-uploads number" id="director-uploads1" data-number="0" data-changed="0">
//some data
</div>
<button type="button" class="btn btn-success" id="add-director">Add Additional Director</button>
jQuery's clone() method should help you:
$(document).ready(function() {
var number = parseInt($('#director-uploads1').data('number'));
function clone(){
var director = $('.director-uploads-hidden').clone(true); //true will cause it to clone all associated data and events as well
director.data("number", number+1);
director.removeClass("director-uploads-hidden");
director.css("display", "block");
//if you want to add any other extra data or events, do it here before appending the object
$('#director-uploads1').append(director);
number++;
}
$("button#add-director").on("click", clone);
});
See https://api.jquery.com/clone/ for more info on the quirks of this method. You may need to do some more tweaking depending on your precise situation and requirements.

JQuery change id attribute of elements

I have a drag and drop thing which uses clone. I am having a problem with the date clone though because of datepicker. Therefore, I need to make sure each cloned datepicker has a unique id. A cloned element looks like the following
<div data-type="date" class="form-group">
<label class="control-label col-sm-5" for="dateInput">Date Input:</label>
<div class="col-sm-3">
<input type="text" name="dateInput[]" class="form-control date_picker" id="dateInput">
</div>
</div>
So if I clone two date inputs, I will have two of the above. Now on submit, I clean all of the cloned html, doing things like removing the data-type. At this stage, if there is a cloned date input, I need to give it a unique id. At the moment I am doing this
$("#content").find(".form-group").each(function() {
var html = $(this).attr('class', 'form-group')[0].outerHTML.replace(/ data-(.+)="(.+)"/g, "");
var input = $(this).find('input');
var i = 0;
if(input.attr('id') == 'dateInput') {
alert("TEST");
input.attr("id",'dateInput' + i).datepicker();
i++;
}
console.log(html);
dataArray.push(html);
});
The TEST alert fires twice as it should do if I clone 2 date inputs. However, the id attributes do not seem to change when I output the html to the console. I have set up the following Fiddle to demonstrate that the id of the element is not changing.
Any advice on getting this to change appreciated.
Thanks
Try defining dataArray, i outside out submit event, .each() , using .map() , .get() , .attr(function() {index, attr}) , .outerHTML
$(function() {
// define `i` , `dataArray`
var i = 0, dataArray = [];
$('#content').submit(function(event) {
event.preventDefault();
$("#content").find(".form-group").each(function() {
var html = $(this).attr('class', '.form-group')[0]
.outerHTML.replace(/ data-(.+)="(.+)"/g, "");
dataArray.push($(html).map(function(_, el) {
// adjust `input` `id` here , return `input` as string
return $(el).find("input").attr("id", function(_, id) {
return id + (++i)
})[0].outerHTML
}).get()[0])
});
$("#output")[0].textContent = dataArray.join(" ");
console.log(dataArray)
});
});
jsfiddle https://jsfiddle.net/mLgrfzaL/2/

Jquery multiple plus/minus script

I have multiple forms on a page and also multiple input boxes with plus/minus signs.
I'm having trouble to get those input boxes to work seperately. Probably because of some wrong/same id's or something like that or maybe a wrong setup of my code. The thing is I can't find my error in the code and I don't get any errors in my console.
What I have:
function quantity_change(way, id){
quantity = $('#product_amount_'+id).val();
if(way=='up'){
quantity++;
} else {
quantity--;
}
if(quantity<1){
quantity = 1;
}
if(quantity>10){
quantity = 10;
}
$('#product_amount_'+id).val(quantity);
}
And my html:
//row 1
<div class="amount"><input type="text" name="quantity" value="1" id="product_amount_1234"/></div>
<div class="change" data-id="1234">
+
-
</div>
//row 2
<div class="amount"><input type="text" name="quantity" value="1" id="product_amount_4321"/></div>
<div class="change" data-id="4321">
+
-
</div>
I thought something like this would do the trick but it doesn't :(
$(document).ready(function(){
$('.change a').click(function(){
var id = $(this).find('.change').data('id');
quantity_change(id)
});
});
Any help greatly appreciated!
You should use closest() method to get access to the parent div with class change, then you can read the data attribute id's value.
var id = $(this).closest('.change').data('id');
alert(id);
Since you are already binding the click event using unobutrusive javascript, you do not need the onclick code in your HTML markup.
Also your quantity_change method takes 2 parameters and using both, but you are passing only one. You may keep the value of way in HTML 5 data attributes on the anchor tag and read from that and pass that to your method.
<div class="change" data-id="1234">
+
-
</div>
So the corrected js code is
$(document).ready(function(){
$('.change a').click(function(e){
e.preventDefault();
var _this=$(this);
var id = _this.closest('.change').data('id');
var way= _this.data("way");
quantity_change(way,id)
});
});
Here is a working sample.

How to handle the same jQuery event handler on multiple elements?

Suppose you have the following code to update many elements:
<div class='item'>
Name:<input type='text' name='name' data-id='123' value='Name 1'>
<button class='update'>update</button>
</div>
<div class='item'>
Name:<input type='text' name='name' data-id='456' value='Name 2'>
<button class='update'>update</button>
</div>
And JavaScript to handle the update:
function updateName(name, id){
...
}
What is the jQuery handler that can find the value and id and call updateName?
$('button.update').click(function() {
name = ?
id = ?
updateName(name, id)
}
EDIT:
The expected behavior is that when the user updates the input field, the updated value is sent to updateName(), not the original value.
Also, note that the data-id and value are on the input, not the button.
http://jsfiddle.net/e3g6nfc1/8/
Inside event handlers this is the unwrapped DOM element
$('button.update').click(function() {
var name = this.name
var id = $(this).data('id');
updateName(name, id)
}
note that you want var in this case or else name and id jump out of the scope of that function and possibly become global variables.
I've argued before that this is awkward and bad to use. You can achieve the same effect without using it like so:
$('button.update').click(function(e) {
var name = e.currentTarget.name
var id = $(e.currentTarget).data('id');
updateName(name, id)
}
You also don't have to use jquery for data. on reasonably modern browsers $(domElement).data('foo') is equivalent to domElement.dataset['foo']
Edit: Not sure if I missed this in the question or if it got edited but it seems like you're asking not for attributes on the button but the element before it. In that case you want $.fn.prev which will look something like this
$('button.update').click(function(e) {
var $prev = $(e.currentTarget).prev();
updateName($prev.name, $prev.data('id'))
}
note that this assumes that the input element is directly before the button. If you want to find the closest preceding input element you would use $.fn.prevAll
var $prev = $(e.currentTarget).prevAll('input').last();
Like this:
$('button.update').click(function() {
name = $(this).attr('name');//to get value of name attribute
id = $(this).data('id'); // to get value of attribute data-id
updateName(name, id)
}
You may also use prop() method to get name or data-id:
name = $(this).prop('name');
id = $(this).prop('data-id');
But best is to use data() method for data-* attribute.
Not sure why the answers here are trying to find the input attributes on the button element...
<div id="container">
<div class='item'>
Name:<input type='text' name='name' data-id='123' value='Name 1'>
<button class='update'>update</button>
</div>
<div class='item'>
Name:<input type='text' name='name' data-id='456' value='Name 2'>
<button class='update'>update</button>
</div>
</div>
Delegating the events to attach only to the container (selecting only those children with .update class), catching them as they "bubble up". previousElementSibling used to target the input but jQuery selectors could also be used to find it if the layout were more complex.
$('#container').on('click','.update',function(e) {
updateName(
e.currentTarget.previousElementSibling.name,
$(e.currentTarget.previousElementSibling).data('id')
);
});
JSFiddle

Categories