简体   繁体   中英

Ruby on Rails - JavaScript in dynamically generated partials

I know putting JavaScript in partials is a bad idea because the page will have to load up a new script every time a new partial is loaded. I am aware of and have read this question , but its answer did not work for me (putting the script into app/javascripts/application.js). I think it is because I am working with partials that are dynamically generated onto the page. I think the dynamically generated partial does not react to the script loaded up on the initial page.

For example, I have a "Rule" div with a select input that has a script to do something when the select input is changed. This works for every Rule div that is generated on page load. But then there is also a "+" or "ADD" button which will dynamically generate more Rule divs which do not respond to the script, unless that script is in the partial.

Is there a good way to keep the script out of the partial when the partial is dynamically generated?

JQuery sets listeners on page load (ie $(selector).on(etc.) ), so it doesn't listen for events on dynamically added elements. There is a way around it, though. You need to use what is called a delegate.

$(document).ready( function() { 
    $('body').on('change', 'input.selector', function(e) {
        // do something
    });
});

I'm not sure what your event (here I put change ) or selector for the select you are using (here I put input.selector ), but if you replace those with the appropriate information, it should work even with dynamically added elements.

You can use JQuery to execute the code only after the document has loaded onto the DOM:

$( document ).ready(function() {
    //Call your functions here
});

That way, your JS will have access to whatever is on the page, because you are ensuring that it is fully loaded.

If your divs are not in place on document ready, you can use event delegation, as suggested by ptd. Basically what this means is that you install a handler on a parent div (which will be present on document ready) which says, "hey, when you click on this dynamic div inside of me, call this function".

$('div#master').on('click', 'div.dynamic', function(event) { 
    console.log("action here") 
    var $dynamicDiv = $(event.currentTarget) //The current Target is the thing you clicked on, not the parent.
});    

If you are adding elements to the DOM using AJAX calls, but want to keep your JavaScript in your assets folder only, here's a quick and clean way to accomplish this.

// /app/assets/javascript/foo.js

// On intial page load
$(document).ready(function() {
  yourJavaScriptForPartials();
});

// After a subdomain field is loaded via AJAX
$(document).ajaxComplete(function() {
  yourJavaScriptForPartials();
});

function yourJavaScriptForPartials() {
  // Insert your javascript here. 
};

Now, any JavaScript you put in the yourJavaScriptForPartials() function will be available both to the initially loaded DOM, and to any DOM elements added via AJAX. For reference, here is the JQuery page for the ajaxComplete event listener.

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