Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Sections in Partial Views in MVC 4.0

I want to include scripts in my partial views when I have cases where I need to initialize jQuery ui on specific elements. It really belongs with the partial and not the containing page or the layout.

Supposedly there's a way to do it in MVC 4, but I can't seem to find any info on it.

like image 218
Lucent Fox Avatar asked Sep 14 '12 18:09

Lucent Fox


2 Answers

I also had a similar issue. Hope this helps. We wanted to have a view that contains a common header section that displays some data and another section that should dynamically change when we click on a link in our page. (something similar to a tab) Since we didn't want to reload the header section multiple times, we decided to have a container view and a place holder div that will be used to load a partial view dynamically when we click on a ajax link. However, partial views that got loaded into the place holder had lot of javascript code and we couldn't include all the code that were used by different partial views into a single javascript file and refer it from the container view as there were some conflicting functions. Introducing namespaces to fix that issue also wasn't very efficient approach as all the javascript logic would still have been loaded unnecessarily. Doing a bit of googling made me realize that having a script section in a partial view is not going to work. I tried to define a section in my view using @RenderSection("partialScripts", required: false) unsuccessfully as RenderSection only works in a layout view. Following is the approach i took to overcome this issue. scripts section that is defined in the layout view can contain any valid markup. so i decided to have a div that will help me to load scripts dynamically inside the scripts section of my container view. OnSuccess event handler of the action link was used to attach the scripts dynamically. Here is the code for my container view.

<ul>
    <li>
        @Ajax.ActionLink("Partial One", "PartialOne", ajaxOptions: new AjaxOptions
                     {
                         HttpMethod = "Get",
                         InsertionMode = InsertionMode.Replace,
                         UpdateTargetId = "container",
                         OnSuccess = "loadScriptsDynamically('PartialOne')"
                     })
    </li>
    <li>
        @Ajax.ActionLink("Partial Two", "PartialTwo", ajaxOptions: new AjaxOptions
                     {
                         HttpMethod = "Get",
                         InsertionMode = InsertionMode.Replace,
                         UpdateTargetId = "container",
                         OnSuccess = "loadScriptsDynamically('PartialTwo')"
                     })
    </li>
</ul>

<div id="container">
</div>

@section scripts
{
    <script src="@Url.Content("~/Scripts/app/Container.js")"></script>
    <div id="dynamicScripts"
         data-partial-one="@Url.Content("~/Scripts/App/PartialOne.js")"
         data-partial-two="@Url.Content("~/Scripts/App/PartialTwo.js")">
    </div>
}

Code from the controller class

    public PartialViewResult PartialOne()
    {
        return PartialView("_PartialOne");
    }

    public PartialViewResult PartialTwo()
    {
        return PartialView("_PartialTwo");
    }

Container.js file contains the logic that will dynamically load the necessary scripts for different partial views.

function loadScriptsDynamically(name) {
    var script = document.createElement('script');
    var dynamicScriptsDiv = document.getElementById('dynamicScripts');
    var dynamicScriptDivJQuery = $('#dynamicScripts');
    dynamicScriptDivJQuery.empty();
    if (name === 'PartialOne') {
        script.src = dynamicScriptDivJQuery.data('partial-one');
        dynamicScriptsDiv.appendChild(script);
    } else if (name === 'PartialTwo'){
        script.src = dynamicScriptDivJQuery.data('partial-two');
        dynamicScriptsDiv.appendChild(script);
    }
}

We can't use jQuery to append a script element to a div due to some restrictions. But we can use some old fashioned javascript code to create a script element and append it to dynamicScriptsDiv. Please note that i am accessing the script paths i previously attached to dynamicScriptsDivusing using some data- attributes as our MVC app runs in IIS server and we didnt want to hard code them.

Attaching to events after the script is dynamically loaded was our next challenge. By using an immediate invocation function i was able to register all my event binding code and any initialization logic i have to perform using following code.

(function initPartialOne() {
    $('#myButton').click(function() {
        setLabelText();
    });
})();

function setLabelText() {
    $('#myLabel').text('One was clicked');
}

And finally the code for one of my partial views.

<label id="myLabel">[Message]</label>
<input type="button" id="myButton" value="Click me partial one"/>
like image 167
Nuwan Avatar answered Sep 29 '22 17:09

Nuwan


This has not been possible in ASP.NET MVC 3 (See second comment in this post). Sections can only be used in (main) views, not in partial ones.

I'm currently unable to find any resources according to MVC version 4 but a short test in Visual Studio also fails for MVC 4 unless you render the whole partial view inside of the section.

Nevertheless I would not recommend to do things like this. I've been experiencing caching issues in the past with donut-caching partial views for example. Caching the partial views resulted in code not being executed and caused that neccessary javascript code has not been rendered. So I recommend to put everything you need for the partial view in the partial view itself or (what would even be better) think about a clear design and put all your javascript code in one minified javascript file that is loaded once for the whole page (and then is cached in the browser's cache).

like image 41
Peit Avatar answered Sep 29 '22 17:09

Peit