简体   繁体   中英

Render Scripts-Section after scripts were loaded in ASP.NET Core PartialView

In an ASP.NET Core app, I've a dashboard with widgets. Every widget has its own PartialViews, so the full page is generated in the following way:

-Layout.cshtml

--Dashboard.cshtml

--- Widget1.cshtml

--- Widget2.cshtml

Following best practices according to fast page load times, JavaScript is loaded before the closing </body> tag in Layout.cshtml. After that, there is a section for custom JS, which I commonly use to initiate objects on page load. So this section looks like this:

<script asp-append-version="true" type="text/javascript" src="~/clientscript/page.min.js"></script>
@RenderSection("Js", required: false)

In my Views, which are using the Layout.cshtml as layout (in this example, its Dashboard.cshtml), I can define a section like

@section Js {
    // Js Code here
}

which is rendered after the script tag containing all script files. So I can be sure, that all dependencies like jQuery or custom classes are avaliable here.

But I also need to do this in widgets like Widget1.cshtml for example. The problem is: I load the PartialView Widget1.cshtml in Dashboard.cshtml. In the documentation is written , that this is not possible:

If you declare a Razor section in a partial view, it will not be visible to its parent(s); it will be limited to the partial view.

But that's exactly what I need. Is there a way to work around this limitation? Shortly, the goal is to inject JavaScript from a PartialView to the LayoutView, with an regular View between them.

The only way I know is the usage of setInterval() with a low interval like 50ms, and check there if jQuery or some of my custom class is defined in a loop until they are. Its a JS solution yes. But it makes it possible to include the script-block directly in the PartialView without making usage of sections. It fits well when you depend on a single variable like jQuery.

But I need to wait for custom classes to get loaded. They're included after jQuery. So writing a generic function like waitForTypeLoaded(type, callback) is not possible. It would cause me to write always the raw setInterval() code, which seems not a smart solution for me.

Something I did to get my scripts to run after Jquery was done loading was in my Partial Views and View Components I used the "DOMContentLoaded" event to load all my jQuery js script after the page was done loading. That way I could defer the Load of jQuery and Still Have jQuery code on my pages.

<script>
    window.addEventListener('DOMContentLoaded',
        function() {
            $('body')....

        });
</script>

Your problem can be solved as mentioned in my answer to this post: How to render scripts, generated in TagHelper process method, to the bottom of the page rather than next to the tag element?

To sum up, you can create a pair of tag helpers, one that can be located in a partial view and just stores its content in a temporary dictionary, and the other that renders the content at the appropriate position (eg in the layout page). I use it extensively to render small dynamically created scripts as the final scripts of the body.

Hope it helps.

Honestly, I would make one step back and look at architecture once again if you have such dilemmas.

Why not add to required scripts which will be used on a couple of views/partial views to the main layout? In ASP.NET MVC you can use bundling mechanism (or you can write our own) - minify and bundle them with other required. It won't be heavy...

Your approach looks like unnecessary complicated.

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