Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I define partial views with dynamic JQuery scripts if bundled scripts are rendered at the bottom of the page?

I have a web application using MVC4 and Razor views that utilize a lot of JQuery and other plugin scripts.

For speeding up the rendering of views, I believe that in general, it is good practice to render the scripts at the bottom of the body, so the layout (much consolidated) looks like the following:

<body>
    @RenderBody()

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/other")

    @RenderSection( "Scripts", false )
</body>

The Scripts section allows particular views to add additional JQuery functions, and they are guaranteed to be rendered after the JQuery library. So far, so good.

Now consider the following snippet in a view, which renders a partial for each item in a collection:

@foreach (var item in Model.Items)
{
    Html.RenderPartial("_MyPartial", item);
}

This partial (_MyPartial) needs to render JQuery for controls based on collection item details such as the following snippet:

$(function () {
    $("#@(Model.Id)").click(function () {
        // do something when control on partial with id Model.Id is clicked
        alert("I've been clicked!");
    });
});

The partial view JQuery functions do not get executed, because the JQuery library is not loaded prior to the _MyPartial scripts for each collection item. Running in chrome debugger shows $ not defined, which confirms this.

I could do something real ugly, such as replicating each foreach statement in the scripts section for all views that call the partial and then have the parent view generate the scripts. But, this in effect kills the re-usability of the partial view.

Is there a way to get Razor partial view scripts to render late (such as in parent scripts section), or a different approach to this issue?

like image 553
Dave Clemmer Avatar asked Feb 01 '14 22:02

Dave Clemmer


1 Answers

Unfortunately sections are not supported in partial views. One possibility is to write custom helpers as I illustrated in this post: https://stackoverflow.com/a/9663249/29407

This would allow you to have a placeholder helper invoked at the end of the document which will render all scripts that have been registered in partials.

This being said, it is usually a better idea to expose the client side functionality that your partial needs as a jQuery plugin. Then it is trivially easy to invoke this plugin on some DOM elements:

$('.someElement').somePlugin();

This way you no longer need to be doing any $("#@(Model.Id)") in your partials. The partials shouldn't have any scripts in them normally.

like image 138
Darin Dimitrov Avatar answered Sep 28 '22 05:09

Darin Dimitrov