Jquery dynamic dropdown event not firing - javascript

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.

Related

Dynamic Modal Bootstrap

I have a table like:
When user selects Edit, it opens up a bootstrap Modal containing all td of the tr the Modal is launched from. What I've done so far is:
Get Row Index on Edit Click:
$(document).on('click', '#editNominHref', function(e) {
var global_edit_row = $(this).closest('tr').index();
$('#editNomiModal').modal('show');
});
What I want is:
$('#editNomiModal').on('show.bs.modal', function () {
$("#Name_feild_of_Modal").val(name_in_td_of_nth_Tr);
// ..Similar for DOB, Relation and share%..
});
Question:
How do I pass the tr index from Edit.click to Modal.show function?
I don't believe you can pass data directly to the modal. However, you can use data attributes to modify the DOM which can then be read from the show.bs.modal event. Something like this:
$(document).on('click', '#editNominHref', function(e) {
$('#editNomiModal')
.data('row-index', $(this).closest('tr').index())
.modal('show');
});
$('#editNomiModal').on('show.bs.modal', function () {
var $tr = $('#myTable tr').eq($(this).data('row-index'));
var serial = $tr.find('td:eq(0)').text();
var name = $tr.find('td:eq(1)').text();
// and so on...
$("#Serial_field_of_Modal").val(serial);
$("#Name_field_of_Modal").val(name);
// and so on...
});
When you open the modal can't you just clone the <tr> and insert into modal-content?
$(document).on('click', '#editNominHref', function(e) {
var content = $(this).closest('tr').html();
$('#editNomiModal').find('modal-content').html(content).modal('show');
});
Obviously more formatting would be required.

Some questions around clone/copy TR

I have this code for clone/copy a tr element from a modal to a page.
$(function () {
$('#toggleCheckbox').on('click', function () {
var $toggle = $(this).is(':checked');
$("input:checkbox").attr('checked', $toggle);
$('#btnAplicarNorma').prop('disabled', !$toggle);
});
$('#resultadoNormaBody').on('change', 'input[type=checkbox]', function () {
var $my_checkbox = $(this);
var $my_tr = $my_checkbox.closest('tr');
if ($my_checkbox.prop('checked')) {
$my_tr.addClass('copyMe');
}
var $all_checkboxes = $my_checkbox.closest('tbody').find('input[type=checkbox]');
$all_checkboxes.each(function () {
if ($(this).prop('checked')) {
$('#btnAplicarNorma').prop('disabled', false);
return false;
}
$('#btnAplicarNorma').prop('disabled', true);
});
});
$('button#btnAplicarNorma').on('click', function (ev) {
var $tr_to_append = $('#resultadoNormaBody').find('tr.copyMe');
$('#tablaNorma').removeAttr('style');
$('#alertSinNorma').hide();
if ($tr_to_append.length) {
$tr_to_append.find('input[type=checkbox]').prop('checked', false);
$tr_to_append.clone().appendTo('#normaBody').removeClass('copyMe');
$tr_to_append.removeClass('copyMe');
$(this).prop('disabled', true);
}
});
});
But I'm having some issues:
If I mark all checkboxes using the first on the table head then I the code stop working and doesn't clone any tr even if all of them are marked
How do I avoid to clone/copy the same tr twice?
It's possible to modify the checkbox before clone it? If you take a look at the example you'll notice how the clone tr copy exactly as the one on the modal and I want to uncheck the checkbox first, it's possible?
Here is a fiddle to play with, any advice?
The main problem is that your checkboxes inside the table do not really get properly triggered when you programmatically set them selected. To make sure all associated Events get properly triggered you should be triggering a .click() event instead:
$("#resultadoNormaBody").find("input:checkbox").click();
to ensure that you don't end up with duplicate clones the easiest thing is to not clone all the rows in one batch, but iterate thru them, and comparing the html to the ones that have already been added like this:
//fetch all the rows that have already been cloned
var clonedRows = $("#normaBody").find("tr");
//iterate thru all the rows that have been checked
$.each($tr_to_append, function (i, v) {
var added = false;
//fetch their html (for easier compare)
var currentRowHtml = $(v).html();
//now compare against the rows that have already been cloned
$.each(clonedRows, function (i, cRow) {
var clonedRowHtml = $(cRow).html();
if (currentRowHtml == clonedRowHtml) {
added = true;
}
});
//if the row hasn't been added yet- go ahead and clone it now
if (!added) {
$(v).clone().appendTo('#normaBody').removeClass('copyMe');
}
});
Here's a link to your updated fiddle:
http://jsfiddle.net/wq51zL9x/4/
Here is some more info on comparing table rows: Compare two tables rows and remove if match
and here's the more elaborate answer to using .click()
Need checkbox change event to respond to change of checked state done programmatically

jQuery on change binding with jQuery produced HTML

I have chained select lists which tags for new select box generated by ajax success and data populated via AJAX response.
The is at below however, for quick summary:
on "change" event supposed to work with all select tags which name starts with "n-". But it is not.
var loading = '<div class="span3" id="loading"><div style="height:264px; background: url(/assets/frontend/img/loading_searching.gif) 50% 50% no-repeat;"></div></div>';
function count_selectes() {
return $('select').length;
}
function generate_bs_span(div_class,div_id) {
return $('<div></div>').addClass(div_class).attr('id',div_id);
}
function generate_category_select(sname, sid, sclass, soptionList) {
var els = $("<select></select>").attr("size", '15').attr("id", sid).attr("name", sname).addClass(sclass);
$.each(soptionList, function (i, data) {
els.append("<option value="+data.id_map+">" + data.map_text + "</option>");
});
return els;
}
var sDIndex = 1;
$(function() {
$('select[name^="n-"]').on('change',function(e){
alert('clicked');
var fragment = $(this);
var slID = $(this).val(); // selected_id
var dSrc = $(this).data('source'); // data-source
var dChl = $(this).find(':selected').data('children'); // data-children
var sCnt = count_selectes(); // select count
var cSID = explode('-',$(this).attr('id')); // id for current selection list
var cSSI = parseInt(cSID[1])+1; // starting index + 1 for removing unused select boxes
++sCnt;
for (var i=parseInt(cSSI);i<parseInt(sDIndex)+1;i++){$('#d-'+i).remove();}
$.ajax({
url: '/ilan/fetch_sub_categories',
data: {id:slID,dsrc:dSrc,dchl:dChl},
beforeSend:function(){
$(this).parent('div').after(loading);
},
success:function(data){
$('#loading').remove();
$(fragment).parent('div').after(generate_bs_span('span3','d-'+sCnt));
$('#'+'d-'+sCnt).html(generate_category_select('n-'+sCnt,'s-'+sCnt,'cat_select',data));
++sDIndex;
enable_select_tracking();
},
error:function(){
$('#loading').remove();
alert('ajax returns error');
}
});
});
});
new select box generated by ajax success
You need to use Event Delegation. You have to use .on() using delegated-events approach.
i.e.
$(document).on('event','selector',callback_function)
Example
$(document).on('change', 'select[name^="n-"]', function(){
//Your code
alert("clicked me");
});
In place of document you should use closest static container.
The delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, we can use delegated events to bind the click event to dynamically created elements and also to avoid the need to frequently attach and remove event handlers.

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 Calculate Issue

I am creating an Invoicing System, using jquery.calculate.
var newIDSuffix = 2;
$(".invoice_items").delegate('#add-row', 'click', function () {
var lastRow = $("tr.lastrow");
var cloned = $("tr.default").clone().removeAttr('class');
cloned.find('td#total_item_1').each(function() {
$(this).attr('id', 'total_item_'+2);
});
cloned.find('input, select').each(function() {
var id = $(this).attr('id'),
name = $(this).attr('name');
id = id.substring(0, id.length-1) + newIDSuffix;
$(this).attr('id', id);
});
cloned.insertBefore(lastRow).find('input:text').val('');
newIDSuffix++;
});
// update the plug-in version
$("#idPluginVersion").text($.Calculation.version);
// bind the recalc function to the quantity fields
$("input").bind("keyup", recalc);
// run the calculation function now
recalc();
$("input").bind("keyup", recalc);
// run the calculation function now
recalc();
Here's what I have done so far. http://jsfiddle.net/aliharis/VXZe8/
The problem is once I add a row dynamically, and when I enter the values to it, It doesn't update the amount column and total. But If I enter values for the dynamically added row and go back to first row and enter values, It makes the calculation including the dynamically added fields.
I couldn't figure out whats going wrong.
add the line:
cloned.bind("keyup", recalc);
right after this line:
cloned.insertBefore(lastRow).find('input:text').val('');
to bind a click event to the new element.
.. or alternatively use .on() instead of bind here:
$("input").on("keyup", recalc);

Categories

Resources