Load document ready script from child control? - asp.net-mvc

Can I put javascript in a child control and expect it to execute on document load?
My child control renders HTML correctly however the javascript is not rendered to the page and of course does not execute. Is it possible to do what I am asking and if so what am I doing wrong?
In my parent .cshtml page I have:
#Html.Action("LoadToolsControl", "ToolsControl", new { area="Common" })
ToolsControl.cshtml looks like this:
<div style="overflow:auto;height:190px;">
<ul id="ToolsControlToolsList"></ul>
</div>
#section scripts {
<script type="text/javascript">
$(document).ready(function () {
alert('hi there');
});
</script>
}
The bottom few lines of my LayoutPage look like this:
#RenderSection("scripts", required: false)
</body>
</html>

Your layout page doesn't really "interact" this way with the child action. Think of it like an independent subpage that is inserted into the parent. Specifying the #section scripts in the child won't work with #RenderSection in the parent.
Try to use Partial instead of child action or tell us a little bit more about why you are doing it like this.

Related

What is #section scripts and what it is used for

I have downloaded a chat example from the Microsoft website. I have been following several tutorials but I have never seen the #section script{} before I have done scripts without this block of c# code (#section script{}) and it seem to work fine but in this instance of the chat application using signal R when I do take the scripts outside the block it does not work.
#section scripts {
<!--Script references. -->
<!--The jQuery library is required and is referenced by default in _Layout.cshtml. -->
<!--Reference the SignalR library. -->
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="~/signalr/hubs"></script>
<!--SignalR script to update the chat page and send messages.-->
<script>
$(function () {
// Reference the auto-generated proxy for the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call back to display messages.
chat.client.addNewMessageToPage = function (name, message) {
// Add the message to the page.
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</li>');
};
// Get the user name and store it to prepend to messages.
$('#displayname').val(prompt('Enter your name:', ''));
// Set initial focus to message input box.
$('#message').focus();
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
// This optional function html-encodes messages for display in the page.
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
}
A section allows you to add something in a view which will be added in the layout. ie:-
view
#section scripts {
<script>
alert('foo');
</script>
}
layout
#RenderSection("scripts", false)
now this named section scripts will be rendered where you have specified in the layout.
#RenderSection also has 2 signatures:-
public HelperResult RenderSection(string name) // section required in the view
public HelperResult RenderSection(string name, bool required)
When you define an #section somewhere, lets say the _Layout.cshmtl file, it allows all of your Views to dynamically insert script files or CSS files or what ever into places in the defining page.
This is very nice when, for example, you are using the jQuery UI Datepicker control only on a couple views in your site. So you may not want to globally include the jQuery UI Datepicker script file in your _Layout.cshtml since you are only going to need it on 2 or 3 pages.
#section allows you to include those files only for certain views. It is needed since, a view cannot easily change the contents of the _Layout.cshtml otherwise.
You can also position the #section at the bottom of the layout, for JavaScript files for example, or at the top of the layout, for CSS files. You could also use it to include a sidebar, made in HTML, only in certain views.
Just be aware that Partial Views are not able to use the #section element by default.
There is also one thing that should be added to the answers above that makes the use of "scripts" section crucial in most cases which is also the only reason for me to use this section.
That is, it guarantees that scripts will load after all page contents which is essential. By doing this, you actually make sure necessary elements for your JavaScript code have loaded already and also it is a matter of performance.
To elaborate how it works, I should mention that:
That is a common practice to put the commonly used scripts inside the "_Layout" page to make them accessible among all pages and also prevent their repetition.
All contents of child views are loaded into the _Layout view where #RenderBody() method is called. Except the contents inside #sections of each view.
When we define "scripts" section inside the footer of the layout for common scripts and then add our scripts of child views inside the "scripts" section of each child view we make sure that these scripts will load after the script of the layout that makes the functions in the _Layout available to the scripts of the child views.
Otherwise, the scripts of child views would be loaded where RenderBody() method is called, before the common scripts of the _Layout page.
For Example:
Inside _Layout:
#RenderBody()
<footer>
<script>
$(function CommonlyUsedFunction() {
console.log("text");
});
</script>
#RenderSection("Scripts", required: false)
</footer>
Inside MyView:
<script>
CommonlyUsedFunction(); //Function is not Accessible Here
//It will not be accessible because RenderBody() will load the function before its declaration.
</script>
#section Scripts
{
<script>
CommonlyUsedFunction(); //Function is Accessible Here
</script>
}
I'd just like to add another form of answer here, because it took me a combo of reading all three current answers and some experimenting before I understood it.
I copied some ajax code for a modal popup that was enclosed in #section scripts { } and put it in a view. It worked fine, but I took away the section bit, because it was encapsulated in <script> html - which is normally fine;
My view before:
#Section scripts {
<script> ... my function ... </script>
}
<h1>The rest of the page</h1>
How I normally include a one-off script on a view:
<script> ... my function ... </script>
<h1>The rest of the page</h1>
By doing this, the script is rendered inside the html of the view itself and the popup stopped working. This is because the script accesses elements outside of that view - it needs site-wide access so to be able to stop using #section scripts I would have to be put in the layout file.
But I only really want this script rendered when this view is being used. I don't want to put it in the _layout file and have it loading on every single page.
Lucky me! At the bottom of a default _layout file there's a line (I normally remove, to be honest):
#RenderSection("scripts", required: false)
So by enclosing my <script>s in #section scripts { } on any view, it becomes part of the _layout, and is loaded after all other content (it's right at the bottom of the layout page), but only when that particular view is used.
It basically allows a dynamic layout page which is very clever, I wonder if it's possible to do with stylesheets too.

Angular.js in ASP.Net MVC -- need to reload page twice

I minimized the problem to this simple reproduction. Create new Asp.net MVC app, add Angular.js via nugget.
_Layout.cshtml:
<head>
<!-- Other stuff -->
#RenderSection("JavascriptInHead", required: false)
</head>
_Index.cshtml
#section JavascriptInHead {
<script src="~/Scripts/angular.min.js"></script>
}
<div ng-app>
{{2 + 2}}
</div>
So this works (obviously), however when I click, say About or Contact menu to reload another view and then go back to Home, I get
{{2 + 2}}
Then I click page reload two times and I get
4
Please help me understand this..
Angular bootstraps when the document loads. So if you are loading html that contains angular into your page without doing a full page refresh, you'll need to bootstrap angular manually. Try adding this script to your partial page:
angular.element(document).ready(function() {
angular.bootstrap(document);
});
btw, I for one appreciate you posting a concise example rather than 100 lines of code from your actual project. If your actual project has an app name, however, like this...
<div ng-app="myApp">
then the js you put into your partial page should look like this...
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
Documentation for manually bootstrapping Angular can be found here: https://docs.angularjs.org/guide/bootstrap

ASP.Net MVC page with a section that contains partial view being submitted as part of the form post?

I have a view that contains a partial view that is brought into a #section on the layout page.
How can I include the fields in that partial view in a section in the form collection on submission?
If I put it into the using(Html.BeginForm()){#section } the section does not get placed in the proper place on the form. If I don't include it in the using section the fields don't get submitted as part of the form collection.
Any way to make this work?
#using(Html.Beginform("MyMethod","home", FormMethod.Post)){
#Html.Partial(MyModel)
<input type="submit" value="continue"/>
}
#section LowerLeftBlock{
#HtmlPartial("partials/_additionalformfields")
}
And the layout page:
<div id="body">
#RenderSection("LeftBlock",false)
#RenderBody()
</div>
You could easily use jQuery to copy the additional fields into the form, either when the page is fully loaded or just before the form is submitted. Something like this might do:
<script type="text/javascript">
$(document).ready(function(){
$('#theform').submit(function(){
$("#lowerleftblock input").appendTo("#destinationform");
});
});
</script>
You would obviously need to adjust the css selectors in the sample code above for this to work.
You may want to
See the jQuery docs for more info on appendTo.
See the jQuery docs for more info on selectors.

Having difficulties with simple ajax implementation with jquery

I'm trying to implement simple ajax by using jquery in mvc. I'm just trying to load some contents from another page in the current page. My code is looks like this:
<div>
<ul id="biographies">
<li> Ajax</li>
<li> Index </li>
</ul>
<div id="biography">
The ajax content will appear here...
</div>
<script type="text/javascript">
$('#biographies html.ActionLink').click(function (e) {
var url = $(this).attr('href');
$('#biography').load(url);
e.preventDefault();
});
</script>
</div>
But having some problem as follows:
When I keep the ajax.cshtml file in Home folder under view, its showing content not found, I need to know how to link internal resource in mvc using simple anchor tag not html.actionlink method.
When I keep the ajax.cshtml file in the root directory, it just move to that page rather than loading the contents in first page,which is expected.
Please help. Thanks in advance.
Replace
$('#biographies html.ActionLink')
with
$('#biographies a')

How to implement the partial page loading functionality

I have a application which has very bulky page and i can not reduce the functionality any more. Because of this my every page is taking too much time to load completely.
Is there any way to load the page in sequential manner. Link once i hit the URL few content get displayed immediately and other contents will get displayed one by one?
I our website we are using the Entity framework and RJSResult to render the contents.
Thanks and Regards,
Kamal Kant Pansari
You might use AJAX to delay loading of some page parts. Html.RenderPartial method doesn't help in this case because partial views will be rendered before sending result page to a client.
With jQuery you could do something like this:
<script src="<%= Url.Content("~/Scripts/jquery-1.3.2.js") %>"
<script type="text/javascript">
$(document).ready(function()
{
var url = '<%= Url.Action("ReturnDelayedPartialView") %>';
// show a placeholder image
$("#delayed").html("<img src='<%= Url.Content("~/Content/ajax-loader.gif") %>' />");
// load content
$("#delayed").load(url);
}
</script>
<div id="delayed">
</div>

Resources