简体   繁体   中英

jQuery datepicker not working on dynamically generated HTML

I have this code:

<div id="infants-data"></div>

for( var i = 1; i <= 10; i++)
{ 
        var currInfantDataField = '' +
        '<div class="field">Infant ' + i + ': ' + 
         '<div style="width:600px">' + 
          '<select id="infant-'      + i + '-title" style="border:solid 1px #cccccc;">'+ 
           '<option selected>--Title--</option>'    +
           '<option value="master">Master</option>' + 
           '<option value="miss">Miss</option>'     +   
          '</select>' +
          '<input type="text" id="infant-' + i + '-surname" placeholder="Surname"  style="width:110px; border:solid 1px #cccccc;">' +
          '<input type="text" id="infant-' + i + '-othernames" placeholder="Othernames"  style="width:120px; border:solid 1px #cccccc;">' + 
          '<input type="text" id="infant-' + i + '-birthdate"  placeholder="Date of Birth"  style="width:120px; border:solid 1px #cccccc;" readonly>' + 
         '</div>' +
        '</div>';

        document.getElementById('infants-data').innerHTML += currInfantDataField;

        jQuery( "#infant-" + i + "-birthdate").datepicker({ 
        changeMonth: true,  
        changeYear: true, 
        yearRange:'1900:<?php echo ( date('Y') - 2 ); ?>',
        onSelect: (function(){doSomethingUsefulWithField("infant-" + i + "-birthdate")})
        });
}

For some reason I can't explain, the datepicker is not working.

PS I have tried this and several others like it but they did not work in my case, hence my asking this.

You have two problems in your code, #1 is you keep adding a datepicker and then later overwrite the entire innerHtml - breaking the datepickers added. The other one is related to the event handler which uses the same handler (with same i value) for all datepickers (see fix at Bug#2 below).

One way to fix bug #1 is to add all the html (and update the DOM only once for efficency and not 10 times), and then create all the datepicker

See JSFiddle: http://jsfiddle.net/byhpc73L/2/

Bug #2: You have a bug passing the parameter "i" to the onSelect handler - all handlers will use the same i which will be 11 when the loop finishes. You need a closure to bind the current i value to a function - see below.

eg.

for (var i=1; i<=10; i++) {  ... create html string ... }
.. update DOM from html string

for( var i = 1; i <= 10; i++) {
    jQuery( "#infant-" + i + "-birthdate").datepicker({ 
        changeMonth: true,  
        changeYear: true, 
        yearRange:'1900:2015',
        onSelect:(function(ii) { return function(){doSomethingUsefulWithField("infant-" + ii + "-birthdate")}
                           })(i)   /* note the function gets `i` and returns a function bound to the current value */
    });
}

Rewrite your .datepicker() to traverse down $(document) , which will find your respected new 'html'

    jQuery("#infant-" + i + "-birthdate", document).datepicker({ 
        changeMonth: true,  
        changeYear: true, 
        yearRange:'1900:<?php echo ( date('Y') - 2 ); ?>',
        onSelect: (function(){
            doSomethingUsefulWithField("infant-" + i + "-birthdate")
        })
    });

That, or check to make sure you haven't got any JavaScript errors prior to the .datepicker() initialisation which could be 'blocking' the execution.

You need to delegate the event.

For ease of selecting, add a class to your datepickers

 '<input type="text" class="mydatepickclass"  ....

and then you can use a listener that targets a parent that exists at dom-ready, with this child. Use a parent div, or if none, go all the way out to the body. It also doesn't need to be in the loop.

$("body .mydatepickclass").datepicker({
     //options...  and use $(this) or $this to target the selected items, not i
});

so, to re-write your entire loop,

<div class="wrapper">
<div id="infants-data"></div>

<script>
  for( var i = 1; i <= 10; i++)
   { 
    var currInfantDataField = '' +
    '<div class="field">Infant ' + i + ': ' + 
     '<div style="width:600px">' + 
      '<select id="infant-'      + i + '-title" style="border:solid 1px #cccccc;">'+ 
       '<option selected>--Title--</option>'    +
       '<option value="master">Master</option>' + 
       '<option value="miss">Miss</option>'     +   
      '</select>' +
      '<input type="text" id="infant-' + i + '-surname" placeholder="Surname"  style="width:110px; border:solid 1px #cccccc;">' +
      '<input type="text" id="infant-' + i + '-othernames" placeholder="Othernames"  style="width:120px; border:solid 1px #cccccc;">' + 
      '<input type="text" class="mydatepickclass" id="infant-' + i + '-birthdate"  placeholder="Date of Birth"  style="width:120px; border:solid 1px #cccccc;" readonly>' + 
     '</div>' +
    '</div>';

    document.getElementById('infants-data').innerHTML += currInfantDataField;
 }

 jQuery( ".wrapper .mydatepickclass").datepicker({ 
    changeMonth: true,  
    changeYear: true, 
    yearRange:'1900:<?php echo ( date('Y') - 2 ); ?>',
    onSelect: (function(){doSomethingUsefulWithField($(this).val())})
    });
 </script>

</div>

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