TransWikia.com

How do I reinitialize my jQuery calls after calling .html() to replace content

Stack Overflow Asked by Dan Tappin on December 18, 2020

I have a page with various jQuery calls on initial load (select2, ‘onclick’ etc.). It’s a remote JS form in my Rails app. If the submit fails I have the page reload the form again for the user to correct validations etc.

The issue is all the intial jQuery calls do not persist on the reloaded content (via a .html() call).

I have found a few posts like this:

Reinitialize jQuery after AJAX call

I have fixed most of the original calls like this which now works fine:

$(document).on('keyup', 'input.item_quantity', function(event){
    my code etc...
});

I have others like this which I can’t seem to resolve:

$(function() {
  $('[data-behavior="select2-parent"]').select2({
    ajax: {
      url: 'myurl',
      dataType: 'json'
    }
  });
});

These are all the calls on the document loading and not due to user interaction. I can make these load when the user clicks on the inputs but there is a slight delay between the user click and the select2 kicking in. I need this to persist even when I reload content via the .html().

Calling this direct after reload in the console works:

$('[data-behavior="select2-parent"]').select2();

I added this to the code where my .html() is called but the select2 does not initialize and no console errors.

How have these select2 call bind to the initial elements and ones added afterwards? I suspect I may be missing something small or obvious here.

EDIT: The URL in the select2 AJAX config is also dynamic based on other form input values.

One Answer

You're going to simply have to re-initialize the select2 elements. Your second call after the .html() is not working because the .select2() call is expecting your configuration passed to it like you did when you first initialized. It has no prior knowledge of your configuration, especially if you are replacing the entire .html(). I would recommend saving your configuration to a variable that can be re-used.

const select2Config = {
  ajax: {
    url: 'myurl',
    dataType: 'json'
  }
};

$(function() {
  $('[data-behavior="select2-parent"]').select2(select2Config);
});

Then you can call it again after your .html() call. You may have to destroy the select2 control before re-initializing, which will unbind all of the events to it. If you have a dynamic URL, you can simply override that part of the config to minimize code duplication:

/* ... .html() call here ... */

// get new dynamic URL
const myNewAjaxUrl = /* code to get dynamic url */

// destroy previous select2 instance (may be unnecessary)
// then re-initialize w/overridden config 
$('[data-behavior="select2-parent"]')
  .select2('destroy')
  .select2(Object.assign({}, select2Config, {
    ajax: {
      ...select2Config.ajax,
      url: myNewAjaxUrl,
    },
  );
});

You can look at this answer to see why I call ...select2Config.ajax, to maintain any other AJAX options you have and to only override the url parameter. You could also just do this separately if you thought it looked cleaner:

const newConfig = Object.assign({}, select2Config);
newConfig.ajax.url = /* code to get dynamic url */

$('[data-behavior="select2-parent"]').select2('destroy').select2(newConfig);

Correct answer by Jason Roman on December 18, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP