38

I've created an MVC 4 using the default template, where @Script.Render(~"bundles/jquery") is called after @RenderBody(). As per this post, this is the recommended execution order to prevent the loading of scripts to block the rendering of the page.

I want to add a small jQuery call in my view, or my RenderBody() section. It looks like this, at the top of my view:

<script type="text/javascript">
$(document).ready(function()
{
    $("#eta_table").tablesorter({
        headers: {
            0: { sorter: false }
        }
    });
});

However, this will always throw the error Error: '$' is undefined because jQuery isn't loaded until after the RenderBody().

I can't imagine this is a new problem, it seems like a fairly common task... Any suggestions on how this should be handled?

For reference, here is where the jQuery is loaded:

        @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
</body>

Edit

I ended up moving the script above into my scripts.js file, and loaded it in below jQuery in the layout page, like so:

            bundles.Add(new ScriptBundle("~/bundles/custom").Include(
                    "~/Scripts/Custom/tablesorter.js",
                    "~/Scripts/Custom/scripts.js"));

And the HTML:

        @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/custom")
    @RenderSection("scripts", required: false)
</body>

Except this still seems wrong, as now the scripts are going to have to load for every page that uses the master layout view. It's working, but, is this the best way?

Community
  • 1
  • 1
Tom
  • 2,180
  • 7
  • 30
  • 48

1 Answers1

85

Create a new section MyScripts below all other library scripts

_Layout

@Scripts.Render("~/bundles/jquery")
@RenderSection("scripts", required: false)
@RenderSection("MyScripts", required: false)

MyView

@section MyScripts {
    <script type="text/javascript">
        $("#eta_table");
        ...
    </script>
}

Now your custom page scripts only get loaded once after jQuery is loaded.

Jasen
  • 14,030
  • 3
  • 51
  • 68
  • 21
    Or just use the existing "scripts" section. – Chris Pratt Mar 11 '13 at 20:28
  • 1
    Yup, "scripts" section did it. I did not know exactly what that was doing, thanks for the lesson. This worked. – Tom Mar 11 '13 at 20:34
  • 1
    @ChrisPratt yes, that's certainly true. But I like to use the predefined "scripts" section for libraries that render single line script includes so I made the new section specifically for script I'd write out on that page only. In fact, I'd do a refactor pass to extract "MyScripts" into a separate js file to take advantage of bundling. – Jasen Mar 11 '13 at 20:35
  • 1
    you could also put the `@Scripts.Render("~/bundles/custom")` in the `@section MyScripts{ }` section if you still want to use bundling for custom scripts – mrd3650 Sep 25 '15 at 10:25
  • Solution to **add custom script optionally** with use of if script is defined, check [this](http://stackoverflow.com/a/7357102/2218697) – Shaiju T Sep 10 '16 at 12:09