My entire website is an Ajax website, so all of my views (apart from Layout) can either be loaded normally or via an ajax actionlink. If I put the Javascipt files in with the partial views then all of the code works as expected, but the scripts get loaded multiple times (thus making the user download more scripts, all of them aren't being cached for some reason either).

If I put the script files in my Layout, then they only get loaded once but if a partial view gets loaded then the JS code for that partial view doesn't work obviously, because the scripts were already loaded when the partial view wasn't rendered.

My question is, how can I make the scripts get loaded only once, but also somehow have them affect partial views?

Index view:

<script src="/Scripts/Build/module.min.js"></script>
<script src="/Scripts/Build/upload-index.min.js"></script>

Layout:

<li>
    @Ajax.ActionLink("Upload", "Index", "Upload", new {Area = "Music"}, new AjaxOptions {HttpMethod = "GET", UpdateTargetId = "body-wrapper", InsertionMode = InsertionMode.Replace, OnSuccess = "updateHistory", AllowCache = true }, new {@class = "nav-link"})
</li>

You can see the scripts getting loaded multiple times if they are in the partial view: enter image description here

share|improve this question
2  
Do not put scripts in partial views. If your dynamically loading a partial after the page has been rendered, then you need to use event delegation (using .on() to handle events from elements in the partial) – Stephen Muecke Mar 15 '16 at 22:16
    
What do you mean "affect partial views"? – Balde Mar 15 '16 at 22:16
    
@StephenMuecke I can't use .on(). I am using dropzone plugin in my view and it gets bound as soon as it loads. I need another way. – Martin Mazza Dawson Mar 15 '16 at 22:48
2  
As I noted in my previous comment. In the success callback, after you have added the partial to the DOM, then attach the plugin. You have not shown anything relating to the partial, but it would be something like $(someElementYouJustAdded).dropzone({ .... }); – Stephen Muecke Mar 15 '16 at 23:26
2  
Just make sure your not reattaching the plugin to existing elements - e.g. if the elements has class="dropzone", then use $('.dropone:last').dropzone(); – Stephen Muecke Mar 15 '16 at 23:40
up vote 2 down vote accepted

Scripts should not be in partial views, only the main view or its layout. Not only do you have the duplicate issue you have identified your self, but it can lead to other issues such as invalidating existing scripts.

If you need to handle events associated with dynamically added items then use event delegation using the .on() function. For example

$.(container).on('click', '.someclass', function() { .... }

will handle the click event of elements with class="someclass" that have been added as a child element of container even if they are added after the DOM has been initially loaded.

If you need to attach a plugin to dynamically added elements, then attach it after the element has been added to the DOM, for example

$.get(url, function(html) {
    $(container).append(html); // append the partial view
    $(container).find('someclass:last')..dropzone({ .... }); // attach plugin
});
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.