Using jQuery with partial views in asp.net mvc 4 - c#

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 () { ...

Related

Load partial view after main view

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.

MVC controller action launched from modal crashes losing jQuery context

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

Loading an ASP.Net page inside another ASP.Net page using Ajax

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
});

LoadingElementId in Ajax.BeginForm not displaying the loading image

I have an MVC3 app, and i need to add ajax loading image. I put this on my view
#using (Ajax.BeginForm(
"LogOn","Account",
new AjaxOptions { LoadingElementId = "div_loading" }))
This is my very simple div on the same view:
<div id="div_loading" style="display:none;">
<img src="#Url.Content("~/Content/Images/loading.gif")" alt="" />
</div>
When i click my submit button to post the form back, the loading.gif never appears. My code runs fine, but no loading indicator shows up. And the image is named correctly and in the right place. Does anyone have a clue why?
Update
Apparently, this has something to do with Telerik applications. If i create a regular MVC3 app, it works. When i create a Telerik MVC3 app, it doesnt work. Has anyone else encountered this with Telerik?
You could try this as well from: here
function AjaxBegin()
{
$('#div_loading').show();
}
function AjaxComplete()
{
$("#div_loading").hide();
}
function AjaxFailure(ajaxContext)
{
var response = ajaxContext.responseText;
alert("Error Code [" + ajaxContext.ErrorCode + "] " + response);
}
AjaxOptions:
OnFailure = "AjaxFailure";
OnBegin = "AjaxBegin";
OnComplete = "AjaxComplete";
I prefer to shy away from attaching a loading iamge to every ajax call I make.
The top answer here is a solution to display an ajax spinner (loading image) whenever ajax makes a send call:
Display spinner while waiting For ajax
It has the functionality you need. Just use javascript to attach the display of the image to the ajax calls.
It should be something like:
<script type="text/javascript">
$(document).ready(function () {
BindSpinner();
});
function BindSpinner() {
$("#div_loading").bind("ajaxSend", function () {
$(this).show();
}).bind("ajaxStop", function () {
$(this).hide();
}).bind("ajaxError", function () {
$(this).hide();
});
};
</script>
What this does is display the div on ajax send and hides it upon ajax stop or error for all calls on your page. If you place this script and the div in your _layout it will do this for every Ajax call on your site.
You might want to try this instead. I got it from the SO question here
<div id="div_loading" style="visibility:hidden;">
<img src="#Url.Content("~/Content/Images/loading.gif")" alt="" />
</div>
I had the same issue and was able to solve it changing the name of the element to be hidden/shown. I used camel-case format: "myDivToBeHidden"
The element needs the "display" property set to "none".

Run ajax scripts on page when navigating with 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).

Categories