I have several partial views that have been added to my main view on my MVC site. One of the partial views takes a long time to load however, as it can take a while to retrieve the data for it. Is it possible to load the main view and start loading the partial views, but if the view is still loading then display the rest in the meantime, with the final one showing once it has finished?
On a similar note, while a partial view is loading (or being refreshed) how can I get some kind of "Loading" screen to show over the view area so that the user knows that something is happening?
Thanks
Try the below codes
$.ajax(
{
url: '/Controller/Action',
data: { Id: '1' }, //input parameters to action
beforeSend: function () {
$('#div-result').show();
var img = '<img src="../../Images/loading.ico" />';
$('#div-result').html(img);
},
success: function (data) {
// $('#div-result') -> div in the main view
$('#div-result').html(data);
}
});
As Alexey says, simply add content element(s) where you need the partial views
<div id="partialViewHolder" style="display:none">Ajax content goes here after initial page loads, but it is hidden until then</div>
And then in your javascript, add something like (assuming you have already loaded jquery into the DOM):
<script type="text/javascript">
$(window).load(function () {
$( "#partialViewHolder" ).load( "#Url.Content("Your PartialView Controller Method Goes Here")" );
$( "#partialViewHolder" ).show();
}
</script>
Note that you need to use $(window).load() instead of $(document).ready() as a trigger to allow the page to render while the partial view is loading.
As I understand, you want to get partial view async. You can use Ajax to draw partial view, for example, by using jQuery ajax to get data from server and draw it, when ajax request is done. So your main view will be loading much faster.
Related
I am having a problem that is similar to these two StackOverflow posts here and here. However my situation is just different enough that I'm not able to make the correction needed.
Like those two post I seem to be losing context as the browser does the post controller action.
The scenario is is follows:
Page Loads
User clicks add button.
Modal dialog loads partial view with fields needed to add new object.
Form is completed and user clicks save.
Controller action for add completes (add record just fine) then redirects to the controller action for step 1. The thought was this would close the modal and return user to page in step 1.
The problem is of course that the redirect results in a $ (jquery) is undefined error.
Step 1 controller action:
public ActionResult Configure()
{
....code...
return View("~/FolderPath.../Configure.cshtml", model);
}
Step 2 jQuery to launch modal:
$("#new").click(function (e)
{
e.preventDefault();
var window = $("#window").kendoWindow(
{
content: {
url: "#Html.Raw(Url.Action("CreateEditRecord", "Controller"))",
data: { .... }
}
});
window.data('kendoWindow').center();
});
Step 3 & 4 Modal submit:
$("#save").click(function (e)
{
e.preventDefault();
...some validation stuff here.....
$("#formCreateEditRecord").submit();
});
Step 5 (These are the different methods I have tried and they all lose jQuery context)
public ActionResult CreateEditRecord(NewRecordModel model)
{
...add new record to db etc.....
//return RedirectToAction("Configure");
//return Configure();
//return PartialView("~/FolderPath/CreateEditRecord.cshtml", model);
//tried this last one to return to modal window just trying to figure things out.
}
Edit
#SSA & #Ryios. Your explanations were very clear and do solve the problem but if you could bear with me a few seconds more....
I understand the partial view doesn't have the full weight (scripting tags etc.) of the full page. What I am still unclear of is WHY does it even go back to the partial view? My post controller action in step 5 redirects to configure action which is a full view so I would have expected the page to load the full view.
Does the MVC view engine still render the partial view even just for a few milliseconds before changing and reloading the full page again?
I think 2 steps more,
Manually submit the form.
Return a JsonResult from action CreateEditRecord after a database operation.
//In controller action
public JsonResult CreateEditRecord(NewRecordModel model)
{
// Do your database stuff here....
//Then return Success or Failure based on your database result.
return new JsonResult { Data = new { Result = "Success/Failure" } };
}
Then when you call a submit form.
$("#save").click(function (e)
{
e.preventDefault();
...some validation stuff here.....
$("#formCreateEditRecord").submit(
function(e){
e.preventDefault(); //As we will manually submit the form
$.ajax({
type: "POST",
url: "#Html.Raw(Url.Action("CreateEditRecord", "Controller"))",
data: $(this).serialize(),
success: function(data) {
//here we check if database called resulted in Success/Failure
if(data.Result === "Success")
{
//Write your code to close the dialog.
}else
{
//Show error message or whatever.
}
}
})
});
}
"#Html.Raw(Url.Action("CreateEditRecord", "Controller"))"
That is rendering a partial view. Partial views being what they are, typically don't have the full page weight, e.g. they don't have all your script tags.
When it loads as the content for the modal dialog it (itself) does not have jquery because you don't have script tags to load jQuery on the partial view.
So either, add jquery to your partial view, or refer to jQuery on the parent window.
"Note: I'm not sure if this next code stub will work or not as jQuery might be attached to the dom on the parent window and not find any elements on your Modal Window. I know there is a way to do it though, you just might have to mess with your jQuery code a little bit.
$ = window.parent.$;
$("#save").click(function (e)
{
e.preventDefault();
...some validation stuff here.....
$("#formCreateEditRecord").submit();
});
With Ajax, partial views work because they are used to update portions of the original page. However, with a modal dialog it's an entirely new page (in a sub window).
If you were using an InPage Modal Dialog solution like jQuery UI Dialogs, then you would have jquery available from your original page.
I suggest designing a base template for your partial views, something like
<div class="modal-dialog">
<div class="title">#this.ViewBag.ModalTitle</div>
<div class="body">
#RenderBody()
</div>
</div>
<!--Load Scripts/Styles Here-->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
#RenderSection("scripts", false)
Then you can create partial views that use it, like
#{
Layout = "~/Views/Partials/Dialogs/BaseDialog.cshtml";
}
<p>This is a test dialog</p>
#section scripts
{
<script src="anotherscripttoaddhere" />
}
I have a View with the following layout
The parent View is composed of several PartialViews as ilustrated in the picture. One of which is a list where each item has a corresponding Edit button which loads the item into another PartialView, but this is loaded via ajax into a modal dialog-bootstrap. This part works fine.
The problem I have is that no script or jquery event related to the controls of this modal gets executed. For example datepicker widget is never displayed, can not capture the change event of the dropdown, or capture the submit event for the form or the click event of Submit button.
All the scripts are placed in the main View. for example this is the event handler for the modal submit:
$(function () {
$('#myModal form').on('submit', function () {
console.log("okk");
clearErrors();
$.post($(this).attr('action'), $(this).serialize(), function (data, status) {
$('#myModal').modal('hide');
$("#details").html(data);
}).error(function (error, status, a, b) {
$('.modal-body p.body').html(error.responseText);
});
return false;
});
});
In my _Layout.cshtm I have included the necessary scripts (I think):
#Scripts.Render("~/js")
#Scripts.Render("~/bundles/globalization")
#RenderSection("scripts", required: false)
</div>
</body>
where "~/js" is:
bundles.Add(new ScriptBundle("~/js").Include(
"~/Scripts/jquery-{version}.js",
"~/Scripts/jquery-migrate-{version}.js",
"~/Scripts/bootstrap.js",
"~/Scripts/bootstrap-datepicker.js",
"~/Scripts/jquery.validate.js",
"~/scripts/jquery.validate.unobtrusive.js",
"~/Scripts/jquery.validate.unobtrusive-custom-for-bootstrap.js",
"~/Scripts/locales/bootstrap-datepicker.es.js"
));
What could be the problem with my scripts and jQuery for this dialog ? Indications from similar questions in the site have not worked for me so far.
I have tried to express as clearly as possible if something is not understood the code or the illustrations I'm all ears. Thank you
As Partial View is loaded via ajax you need to initialize datepicker after the html is rendered on page so you need to put datepicker initialization script in success function callback:
$.post($(this).attr('action'), $(this).serialize(), function (data, status) {
$('#myModal').modal('hide');
$("#details").html(data);
$("#textBoxID").datepicker(); // initialize datepicker for partial view element here
})
For events you can write delegated events to make them work,choose the closest element of the partial view, i am using container of partial in which you are appending partial view html:
For click event:
$("#details").on("click","#someButtonId",function(){
// write event code here
})
For more detials of on() you can see HERE
If they are being loaded in by ajax you may need to give more context to your selectors.
$(document).on('submit', '#myModal form', function () { ...
Let me preface this question with the fact that I am very new to MVC.
I have an instance where I am rendering a devexpress grid in a partial view.
#Html.Partial("MyGridPartial", Model)
I need to kick off a javascript function at the moment that the model has been populated via this partial view render. I attempted to do this via this. :
settings.ClientSideEvents.EndCallback
I can get to this point, but at that time I do not have the model itself populated so it does no good. I was wondering if anyone is aware of a generic way of kicking/attaching to a partial view render in order to jump into some clientside javascript code.
If it's a PartialView you're rendering in a View on the serverthen Dave's method would work best. Simply wire-up your code to the DOM ready event.
$(document).ready(function(){
//Javascript logic to fire goes here
});
or if you prever the shorthand version...
$(function(){
//Javascript logic to fire goes here
});
If you're rendering a partial view that is being loaded via Ajax then the same method will work. jQuery will run javascript in the html passed back to the client via Ajax once it's attached to the DOM if I recall correctly (feel free to test this I'm just going by memory about it firing once attached to the DOM, but I believe this is a feature of the load() method), assuming the javascript you want to run is in the response. If it's in the parent page sending the Ajax request then you're best bet is to hook it up to the complete event. (I'm populating the parameter on the client side here)
$("#wrapperAwaitingContent").load("/Grids/MyGridPartial", {id: null /*parameters*/}, function(text, status, xhr){
//Javascript logic to fire goes here
});
For me the url used in the .load() call is resolved using the UrlHelper on the server
$("#wrapperAwaitingContent").load("#Url.Action("MyGridPartial", "Grids")", {id: null /*parameters*/}, function(text, status, xhr){
//Javascript logic to fire goes here
});
You also have the option of doing something similar to this using Unobtrusive Ajax. (I'm populating the parameter on the server side here)
#Ajax.ActionLink("Load Data", "MyGridPartial", "Grids", new { id = null/*parameters*/ }, new AjaxOptions() { UpdateTargetId = "wrapperAwaitingContent", OnComplete="onCompleteMethodName" })
There are more properties you can set for the AjaxOptions other than the element to receive the HTML and the method to call when it's finished but I find I'll reuse functions defined in a shared javascript file and populate them only if they are not already populated from there, something like this...
$("a[data-ajax='true']").each(function () {
var ajaxUpdate = $(this).closest("data-ajax-container");
$(this).attr("data-ajax-update", $(this).attr("data-ajax-update") ? $(this).attr("data-ajax-update") : ajaxUpdate);
$(this).attr("data-ajax-mode", $(this).attr("data-ajax-mode") ? $(this).attr("data-ajax-mode") : "replace");
$(this).attr("data-ajax-success", $(this).attr("data-ajax-success") ? $(this).attr("data-ajax-success") : "AjaxSuccess");
$(this).attr("data-ajax-complete", $(this).attr("data-ajax-complete") ? $(this).attr("data-ajax-complete") : "AjaxComplete");
$(this).attr("data-ajax-failure", $(this).attr("data-ajax-error") ? $(this).attr("data-ajax-error") : "AjaxError");
});
If you are rendering this partial as part of the normal flow of a View being rendered, the answer is NO.
Reason for this is the Partial is converted into a string before the parent View is even rendered. At that point, none of your markup has been seen by the browser, no jscript has been read.
If, on the other hand, you rendered the partial in your JQuery Ready function:
$(document).ready(function() {
I think you would need to use an Action Partial (Partial that gets called by an action method). Action Partials can be called within your JQuery Ready function by referencing the url (restfully):
$('#divMyGridPartial').load('/Grids/MyGridPartial/{id}');
and any follow up jscript/jquery functions can be called within the ready series.
The other advantage of an Action Partial, the Model is formed within the action method and can be created contextually to what you need (ideally hinging off an id passed).
I managed to load a distinct page inside a div in another page using jquery ajax. The problem I am encountering is that when I click a button inside this sub page, it cause a postback to the whole parent page. How can I force it to just refresh the panel it resides in?
One more thing. I am not sure I am doing the right thing, but the parent page has its own form with runat=server settings, while the secondary page that is loaded inside the div has its own form. I cannot remove the form from the latter because it causes an error.
I have seen some asp.net ajax tutorials but they do not deal with loading sub pages that havbe their own .net controls. Can anyone guide me to some good tutorial?
Thanks!
You need to create a empty with an Id for example : ajaxDiv
Then you create a jquery script like this :
<script type="text/javascript">
// Called at the loading of a page
$(document).ready(function () {
//here you execute an ajax function
$.ajax({
url: 'the url to retrieve data as string ex : /Webservice/Test',
type: 'get',
async: true of false,
//if the request is successful, you load the content of your div with the strings you loaded
success: function (data) {
$("ajaxDiv").html(data);
}
});
});
</script>
the tips is to load your page into the ajax request.
OK, since you are using jQuery, let's set up that event manipulation.
I assume the following markup:
<button type="submit" id="mySubmitButtonId">Submit</button>
Then, on my page I have the following javascript:
$("#mySubmitButtonId").click(function(event) {
event.preventDefault();
// do here what you want to do instead including refresh of a section via ajax
});
I got a bit of an issue in my ASP.NET MVC project.
I have a chat div in the bottom right corner (like facebook), and of course I do not want this to reload when navigating to all my navigation is ajax.
The problem I am facing is that I use the following code on the top of the view page:
<script type="text/javascript">
$(document).ready(function() {
$('#divTS').hide();
$('a#showTS').click(function() {
$('#divTS').slideToggle(400);
return false;
});
});
</script>
The problem is that this code is only loaded with ajax and does not seem to fire? I would like to run all scripts in the newly loaded view, just as if I hadn't navigated with ajax.
I cannot put this in the site.master as it only loads once and then probably the divs I am trying to hide doesn't exist.
Is there a good way to run scripts in the ajax-loaded div?
You will need to run the scripts in the success callback function of your ajax script. I would recommend you externalizing this into a separate function:
function setupEffects() {
$('#divTS').hide();
$('a#showTS').click(function() {
$('#divTS').slideToggle(400);
return false;
});
}
$(document).ready(function() {
setupEffects();
});
And in the success callback of your script call this function:
success: function(result) {
setupEffects();
}
The Masterpage gets reloaded when you navigate to another View. You can also check if a div exists with $('#div').length > 0.
By the way, "full site" ajax navigation should not be used. Reload your chat on navigation - best put it into a control (makes things easier).