How to create "change" event handlers dynamically? - javascript

I create dropdown dynamically.
Their ids are ddl1, ddl2, ddl3 and so on.
$('#ddl1').focus(function() {
var previous = this.value;
}).change(function() {
var index = $(this).find('selected').index();
$('#ddl1').find('option:eq(' + index + ')').hide();
$('#ddl2').find('option:eq(' + index + ')').hide();
});
$('#ddl2').focus(function() {
...
Creation of 7 dropdowns makes me to write 7 change event handlers.
How to implement dynamically create change event?
My dropdown append methods are:
var x=1;
var dropdown=('#ddl1').html();
$('#btnadd').click(function() {
$('#divname').append('<select id="ddl'+x+' > </select> <option>../option>');
x++;
});

Give a common class to every dropdown and refer to that. Also, use .on() (event delegation) to catch dynamic created elements:
$(document).on('change', '.common-class', function() {
//Your function
var currentId = $(this).attr('id');
});
UPDATE
Add the same class every time you append a select element:
//...
$('#divname').append('<select id="ddl'+ x + '" class="common-class"><option>../option></select>');
SELECTED OPTION
In order to get the selected option:
$('#current-id').find('option:selected').index();

Variant without delegated events to reduce resource usage:
var $dds = $('select');
$dds.each(function(index) {
var $this = $(this);
processDdChange($this);
});
function processDdChange($obj) {
$obj.on('change', function(e) {
var $this = $(this);
alert($this.attr('id') + ' | ' + $this.find(':selected').val());
});
}
https://jsfiddle.net/tasmanangel/2p9mbs7h/

Related

How to preserve old input text value after the change in Javascript? [duplicate]

I have an input text in jQuery I want to know if it possible to get the value of that input text(type=number and type=text) before the onchange happens and also get the value of the same input input text after the onchange happens. This is using jQuery.
What I tried:
I tried saving the value on variable then call that value inside onchange but I am getting a blank value.
The simplest way is to save the original value using data() when the element gets focus. Here is a really basic example:
JSFiddle: http://jsfiddle.net/TrueBlueAussie/e4ovx435/
$('input').on('focusin', function(){
console.log("Saving value " + $(this).val());
$(this).data('val', $(this).val());
});
$('input').on('change', function(){
var prev = $(this).data('val');
var current = $(this).val();
console.log("Prev value " + prev);
console.log("New value " + current);
});
Better to use Delegated Event Handlers
Note: it is generally more efficient to use a delegated event handler when there can be multiple matching elements. This way only a single handler is added (smaller overhead and faster initialisation) and any speed difference at event time is negligible.
Here is the same example using delegated events connected to document:
$(document).on('focusin', 'input', function(){
console.log("Saving value " + $(this).val());
$(this).data('val', $(this).val());
}).on('change','input', function(){
var prev = $(this).data('val');
var current = $(this).val();
console.log("Prev value " + prev);
console.log("New value " + current);
});
JsFiddle: http://jsfiddle.net/TrueBlueAussie/e4ovx435/65/
Delegated events work by listening for an event (focusin, change etc) on an ancestor element (document* in this case), then applying the jQuery filter (input) to only the elements in the bubble chain then applying the function to only those matching elements that caused the event.
*Note: A a general rule, use document as the default for delegated events and not body. body has a bug, to do with styling, that can cause it to not get bubbled mouse events. Also document always exists so you can attach to it outside of a DOM ready handler :)
Definitely you will need to store old value manually, depending on what moment you are interested (before focusing, from last change).
Initial value can be taken from defaultValue property:
function onChange() {
var oldValue = this.defaultValue;
var newValue = this.value;
}
Value before focusing can be taken as shown in Gone Coding's answer. But you have to keep in mind that value can be changed without focusing.
Just put the initial value into a data attribute when you create the textbox, eg
HTML
<input id="my-textbox" type="text" data-initial-value="6" value="6" />
JQuery
$("#my-textbox").change(function () {
var oldValue = $(this).attr("data-initial-value");
var newValue = $(this).val();
});
I have found a solution that works even with "Select2" plugin:
function functionName() {
$('html').on('change', 'select.some-class', function() {
var newValue = $(this).val();
var oldValue = $(this).attr('data-val');
if ( $.isNumeric(oldValue) ) { // or another condition
// do something
}
$(this).attr('data-val', newValue);
});
$('select.some-class').trigger('change');
}
I found this question today, but I'm not sure why was this made so complicated rather than implementing it simply like:
var input = $('#target');
var inputVal = input.val();
input.on('change', function() {
console.log('Current Value: ', $(this).val());
console.log('Old Value: ', inputVal);
inputVal = $(this).val();
});
If you want to target multiple inputs then, use each function:
$('input').each(function() {
var inputVal = $(this).val();
$(this).on('change', function() {
console.log('Current Value: ',$(this).val());
console.log('Old Value: ', inputVal);
inputVal = $(this).val();
});
my solution is here
function getVal() {
var $numInput = $('input');
var $inputArr = [];
for(let i=0; i < $numInput.length ; i++ )
$inputArr[$numInput[i].name] = $numInput[i].value;
return $inputArr;
}
var $inNum = getVal();
$('input').on('change', function() {
// inNum is last Val
$inNum = getVal();
// in here we update value of input
let $val = this.value;
});
The upvoted solution works for some situations but is not the ideal solution. The solution Bhojendra Rauniyar provided will only work in certain scenarios. The var inputVal will always remain the same, so changing the input multiple times would break the function.
The function may also break when using focus, because of the ▲▼ (up/down) spinner on html number input. That is why J.T. Taylor has the best solution. By adding a data attribute you can avoid these problems:
<input id="my-textbox" type="text" data-initial-value="6" value="6" />
If you only need a current value and above options don't work, you can use it this way.
$('#input').on('change', () => {
const current = document.getElementById('input').value;
}
My business aim was removing classes form previous input and add it to a new one.
In this case there was simple solution: remove classes from all inputs before add
<div>
<input type="radio" checked><b class="darkred">Value1</b>
<input type="radio"><b>Value2</b>
<input type="radio"><b>Value3</b>
</div>
and
$('input[type="radio"]').on('change', function () {
var current = $(this);
current.closest('div').find('input').each(function () {
(this).next().removeClass('darkred')
});
current.next().addClass('darkred');
});
JsFiddle: http://jsfiddle.net/gkislin13/tybp8skL
if you are looking for select droplist, and jquery code would like this:
var preValue ="";
//get value when click select list
$("#selectList").click(
function(){
preValue =$("#selectList").val();
}
);
$("#selectList").change(
function(){
var curentValue = $("#selectList").val();
var preValue = preValue;
console.log("current:"+curentValue );
console.log("old:"+preValue );
}
);

How to change order in select2 for multiple, with given order

I am new in select2 js so please help me for selecting value according to given order. Means when i have to store value according to user decided order.
data = [{id:1, name:xyz},{id:2, name:abc},{id:3, name:lmn}]
Suppose I want to show id [1,2] as selected but I am getting [2,1]
Add this code:
$('select').on('select2:select', function(e) {
var element = $(this).find('[value="' + e.params.data.id + '"]');
$(this).append(element);
$(this).trigger('change');
});
Or,
$("select").select2();
$("select").on("select2:select", function (evt) {
var element = evt.params.data.element;
var $element = $(element);
$element.detach();
$(this).append($element);
$(this).trigger("change");
});

jQuery .click() Not Executing for Cloned Element

I'm running into a bug with my code. I am cloning a div so that the user can add multiple customers.
var num = $('.clonedInput').length; // how many "duplicatable" input fields we currently have
var newNum = new Number(num + 1); // the numeric ID of the new input field being added
var newElem = $('#divInput' + num).clone().attr('id', 'divInput' + newNum); // create the new element via clone(), and manipulate it's ID using newNum value
// clear input value for cloned items and do not remove text for del button.
newElem.find('input:not(.DeleteBtn),textarea').val('');
//newElem.find('input[type="submit"]
// Replace clone num with incremental num.
newElem.find(':input').each(function () {
$(this).attr('id', $(this).attr('id').replace(/\d+/, newNum));
$(this).attr('name', $(this).attr('name').replace(/\d+/, newNum));
});
// insert the new element after the last "duplicatable" input field
$('#divInput' + num).after(newElem);
I have provided a delete button to delete rows and I am using the class name for the button to execute a function on click .
$(".DeleteBtn").click(function () {
alert(".DeleteBtn Click Function - " + $(this).attr('id'));
var DelBtnNum = $(this).attr('id');
DelBtnNum = DelBtnNum[DelBtnNum.length - 1];
$('#divInput' + DelBtnNum).remove();
});
I am able to delete the first (original) input row, but any additional customer rows are not deleted.
I have a running demo of the code located here: http://jsfiddle.net/crjunk/FB4BZ/2/
Why will the cloned items not fire the .DeleteBtn.click function?
You need to use event delegation for supporting dynamic elements.
Since you have used jQuery 1.6 in the fiddle
$(document).delegate(".DeleteBtn", 'click', function () {
alert(".DeleteBtn Click Function - " + $(this).attr('id'));
var DelBtnNum = $(this).attr('id');
DelBtnNum = DelBtnNum[DelBtnNum.length - 1];
$('#divInput' + DelBtnNum).remove();
});
if jQuery >= 1.7
$(document).on('click', ".DeleteBtn", function () {
alert(".DeleteBtn Click Function - " + $(this).attr('id'));
var DelBtnNum = $(this).attr('id');
DelBtnNum = DelBtnNum[DelBtnNum.length - 1];
$('#divInput' + DelBtnNum).remove();
});
Another option is to clone the element along with the event using clone(true)
Because the default when using clone is to not clone events. Try passing true to clone():
var newElem = $('#divInput' + num).clone(true).attr('id', 'divInput' + newNum); // create the new element via clone(), and manipulate it's ID using newNum value
jsFiddle example
As the .clone() docs state:
.clone( [withDataAndEvents ] ) withDataAndEvents (default: false)
When you bound the click event, only one div existed, so it is the only one that has a click handler. You should change your code to use on instead of click.
$(document).on('click', ".DeleteBtn", function () {
try going on with .on('click',function(e){ ... }); or use live() selector (but i think live goes deprecated...)
so in your case
$(".DeleteBtn").on('click',function () { ..

Jquery creating checkboxs dynamically, and finding checked boxes

I have information that comes out of a database and gets put into a list with a checkbox by each element. This is how it is currently done:
function subjects(){
$.ajax({
url: "lib/search/search.subject.php",
async: "false",
success: function(response){
alert(response);
var responseArray = response.split(',');
for(var x=0;x<responseArray.length;x++){
$("#subjects").append("<br />");
$("#subjects").append(responseArray[x]);
$("#subjects").append("<input type='checkbox' />");
}
}
});
}
it works fine, but I need a way to pick up on if a checkbox is clicked, and if it is clicked then display which one was clicked, or if multiple ones are clicked.
I can't seem to find a way to pick up on the checkboxs at all.
the response variable is "math,science,technology,engineering"
Because you are populating the Checkboxes Dynamically you need to Delegate the event
$("#subjects").on("click", "input[type='checkbox']", function() {
if( $(this).is(":checked") ) {
alert('Checkbox checked')
}
});
To better capture the data it is better if you encase the corresponding data into a span , so that it can be easier to search..
$("#subjects").append('<span>'+responseArray[x] + '</span>');
$("#subjects").on("click", "input[type='checkbox']", function() {
var $this = $(this);
if( $this.is(":checked") ) {
var data = $this.prev('span').html();
alert('Current checkbox is : '+ data )
}
});
It would be best to give your dynamically injected checkboxes a class to target them better, but based on your code try:
$("#subjects").on("click", "input", function() {
if( $(this).is(":checked") ) {
// do something
}
});
Since your input elements are added dynamically, you need to use jQuery's .on() function to bind the click event to them. In your case you need to use .on() to bind to an element that exist in the DOM when the script is loaded. In your case, the element with the ID #subjects.
This note from the docs is mainly for machineghost who downvoted my answer for no apparent reason:
Event handlers are bound only to the currently selected elements; they
must exist on the page at the time your code makes the call to .on().
To ensure the elements are present and can be selected, perform event
binding inside a document ready handler for elements that are in the
HTML markup on the page. If new HTML is being injected into the page,
select the elements and attach event handlers after the new HTML is
placed into the page.
$('#subjects input[type=checkbox]').on('click',function(){
alert($(this).prop('checked'));
});
or the change event: in case someone uses a keyboard
$('#subjects input[type=checkbox]').on('change',function(){
alert($(this).prop('checked'));
});
simple fiddle example:http://jsfiddle.net/Dr8k8/
to get the array example use the index of the inputs
alert($(this).prop('checked') +'is'+ $(this).parent().find('input[type=checkbox]').index(this)+ responseArray[$(this).parent().find('input[type=checkbox]').index(this) ]);
simplified example: http://jsfiddle.net/Dr8k8/1/
EDIT: Just for an example, you could put the results in an array of all checked boxes and do somthing with that:
$('#subjects>input[type=checkbox]').on('change', function() {
var checklist = [];
$(this).parent().find('input[type=checkbox]').each(function() {
$(this).css('background-color', "lime");
var myindex = $(this).parent().find('input[type=checkbox]').index(this);
if ($(this).prop('checked') == true) {
checklist[myindex] = responseArray[myindex];
}
});
$('#currentlyChecked').text(checklist);
});
EDIT2:
I thought about this a bit and you can improve it by using .data() and query that or store it based on an event (my button called out by its id of "whatschecked")
var responseArray = ['math', 'science', 'technology', 'engineering'];// just for an example
var myList = '#subjects>input[type=checkbox]';//to reuse
for (var x = 0; x < responseArray.length; x++) {
// here we insert it all so we do not hit the DOM so many times
var iam = "<br />" + responseArray[x] + "<input type='checkbox' />";
$("#subjects").append(iam);
$(myList).last().data('subject', responseArray[x]);// add the data
}
var checklist = [];// holds most recent list set by change event
$(myList).on('change', function() {
checklist = [];
$(myList).each(function() {
var myindex = $(this).parent().find('input[type=checkbox]').index(this);
if ($(this).prop('checked') == true) {
checklist.push($(this).data('subject'));
alert('This one is checked:' + $(this).data('subject'));
}
});
});
// query the list we stored, but could query the checked list data() as well, see the .each() in the event handler for that example
$("#whatschecked").click(function() {
var numberChecked = checklist.length;
var x = 0;
for (x = 0; x < numberChecked; x++) {
alert("Number " + x + " is " + checklist[x] + " of " + numberChecked);
}
});
live example of last one: http://jsfiddle.net/Dr8k8/5/
The general pattern to do something when a checkbox input is clicked is:
$('input[type=checkbox]').click(function() {
// Do something
})
The general pattern to check whether a checkbox input is checked or not is:
var isItChecked = $('input[type=checkbox]').is(':checked');
In your particular case you'd probably want to do something like:
$('#subjects input[type=checkbox]').click(function() {
to limit the checkboxes involved to the ones inside your #subjects element.

Jquery dynamic dropdown event not firing

Hi i am trying to create dropdownlists dynamically and populating the contents via an ajax call, this sort of works in the sense that the drop down is created and populated as required but its 'change' event does not fire. I am posting the code below, if anyone can spot something obvious, can you please let me know
regards
$(document).ready(function () {
$("#positions select").change(function (e) {
alert("in");
var id = $("#category_id").val();
$.getJSON("/Category/GetSubCategories/" + id, function (data) {
if (data.length > 0) {
alert(data.length);
var position = document.getElementById('positions');
var tr = position.insertRow(7);
var td1 = tr.insertCell(-1);
var td = tr.insertCell(-1);
var sel = document.createElement("select");
sel.name = 'sel';
sel.id = 'sel';
sel.setAttribute('class', 'category');
td.appendChild(sel);
$.each(data, function (GetSubCatergories, category) {
$('#sel').append($("<option></option>").
attr("value", category.category_id).
text(category.name));
});
}
});
});
});
If your drop down is dynamically generated then you have to bind the change event using .live() handler. live() attaches a handler to the event for all elements which match the current selector, now or in the future.
$("positions select").live("change", function(){
});
Edit
To get the id
$(this).attr("id");
To get value
$(this).val();
To get class name
$(this).attr("class");
inside the change event handler.

Categories

Resources