简体   繁体   中英

how to set onchange function to each append div element

I have a button that adds a new div with a select tag, every option has custom attributes. my problem is when I create a several divs the function only refers to the last div I have created when I am trying to change the first select tag the function not responding.

I have tried to give all of the divs and the input a different id's but that doesn't work.

 <button type="button" class="cam_field_button btn waves-effect waves-light btn-outline-info" >הוסף צלם</button>


var max_fields = 25; //maximum input boxes allowed
var wrapper = $(".camera_men"); //Fields wrapper
var add_button = $(".cam_field_button"); //Add button ID

var x = 0; //initlal text box count
$(add_button).click(function (e) { //on add input button click
    e.preventDefault();
    if (x < max_fields) { //max input box allowed
        x++; //text box increment
        $(wrapper).append('<div>   <br> <select name="cam[]"  id="cam_select'+x+'"  class="form-control" >\n' +
            '                                            <option email="email" phone="phone"  value="צלם 1">צלם 1</option>\n' +
            '                                            <option email="email2" phone="phone2" value="צלם 2">צלם 2</option>\n' +
            '                                            <option email="email3" phone="phone3" value="צלם 3">צלם 3</option>\n' +
            '                                        </select><a href="#" class="remove_field">הסר צלם ' + x + '</a><div>  <input type="hidden" name="cam_email[]" id="cm_email' + x + '">\n' +
            '                                        <input type="hidden" name="cam_phone[]" id="cm_phone' + x + '">'); //add input box
        $('#cam_select'+x).on('change',function () {


            var email =  $('#cam_select'+x+' option:selected').attr("email");
            var phone =  $('#cam_select'+x+' option:selected').attr("phone");

            $('#cm_email'+x).val(email);
            $('#cm_phone'+x).val(phone);
        })
    }

So I have made some changes to your code -

  1. Use classes instead of ids - because you can't have mutliple id's .
  2. I have used template literals here because I like it :)
  3. See how I am using a dynamic jquery listener using $(document).on('change', '.cam_select' + x, function(e) { - the off('change') to ensure that there are no duplicate listeners though here there isn't any.
  4. Also we can get the clicked element using e.target where e is the event object.
  5. Note that I have added one more wrapper to the appended markup - cam and how I am using it using the closest function and then find methods to find siblings and cousins in the cam wrapper which was dynamically inserted.

Check out the demo below illustrating these:

 $(document).ready(function() { var max_fields = 25; var wrapper = $(".camera_men"); var add_button = $(".cam_field_button"); var x = 0; $(add_button).click(function(e) { e.preventDefault(); if (x < max_fields) { x++; $(wrapper).append(` <div class="cam"> <div> <select name="cam[]" class="form-control cam_select"> <option email="email" phone="phone" value="צלם 1">צלם 1</option> <option email="email2" phone="phone2" value="צלם 2">צלם 2</option> <option email="email3" phone="phone3" value="צלם 3">צלם 3</option> </select> <a href="#" class="remove_field">הסר צלם ${x}</a> <div> <input type="input" name="cam_email[]" class="cm_email"> <input type="input" name="cam_phone[]" class="cm_phone"> </div>`); $(document).off('change').on('change', '.cam_select', function(e) { var email = $(e.target).find('option:selected').attr("email"); var phone = $(e.target).find('option:selected').attr("phone"); $(e.target).closest('.cam').find('.cm_email').val(email); $(e.target).closest('.cam').find('.cm_phone').val(phone); }); } }); });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <button type="button" class="cam_field_button btn waves-effect waves-light btn-outline-info">הוסף צלם</button> <div class="camera_men"></div>

You can use class selector instead of ids

Example:

...
$(wrapper).append(<select class="form-control cam_select" >...</select>...)
...
$('.cam_select').on('change',function () {

  var email =  $('option:selected',this).attr("email");
  var phone =  $('option:selected',this).attr("phone");

  $(this).parent().children('.cm_email').val(email);
  $(this).parent().children('.cm_email').val(phone);
})

I have not tried the code, sorry if there are errors

@Allesandro made a move in the right way.

You can detach the event handler code from the creation method (button click) and just supply the event handler logic in the script so it is available to the document and controls we are talking about.

But, you have to make this a so-called jQuery delegated event handler that will work for newly created controls on-the-fly (which is your scenario) and for controls matching the selector that were in the html already when the document was initially loaded: it looks like this:

$(document).on('change', '.cam_select', function () {
  ...
})

You can also be more specific off course and use wrapper for the initial selector instead of document .

Event delegation :

Event delegation allows us to attach a single event listener, to a parent element, that will fire for all descendants matching a selector, whether those descendants exist now or are added in the future.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM