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"/>