0

I have an iframe that contains the following:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="my_container"></div>
<script>
  $.ajax({
    type: 'post',
    dataType: 'json',
    contentType: 'application/json',
    url: 'some_url',
    success: function(data, status, xhr) {
      console.log(data.html); // <div><link href='https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css' rel='stylesheet'><script src='https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js'></script><script>  $('.input-select2').select2();</script><select class='input-select2'></select></div>
      $('#my_container').html(data.html);
    },
  });
</script>

As you see the script inside the iframe pulls a string of HTML/js from an external resource and appends it to #my_container. The pulled HTML/js is:

<div>
  <link href='https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css' rel='stylesheet'>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js'></script>
  <script>
    $('.input-select2').select2();
  </script>
  <select class='input-select2'></select>
</div>

But when the appended scripts run, I get the following error:

Uncaught TypeError: $(...).select2 is not a function

So apparently the select2 function is executed before the library is loaded. If I move the select2.min.js library one level up to the jquery.min.js library everything works just fine. Or if I wrap my select2 function in setTimeout(function(){ ... }, 20); it also works.

So what can I do?

Hyyan Abo Fakher
  • 3,497
  • 3
  • 21
  • 35
JohnSmith1976
  • 536
  • 2
  • 12
  • 35

1 Answers1

0

If I understood, it seems that your jquery snippet is executed before select2 was loaded.

Maybe can you dynamically load the select2 lib with an ajax call, to ensure the library loading.

$.ajax({
  url: "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js",
  dataType: "script",
  success: function(){
    $('.input-select2').select2();
  }
});

As you say, you can also wrap your select2 initialization in a setTimeout() function. It's an unelegant known solution but it works.

See this post: Why is setTimeout(fn, 0) sometimes useful?

roundge
  • 66
  • 9
  • Thanks @roundge but it seems like loading the library with ajax isn't really a solution but rather a hack to circumvent it. – JohnSmith1976 Sep 05 '18 at 12:55