how to check if partial view is loaded and then load javascript - c#

I have a query regarding an issue. As my application using Partial views and these partial views are loaded by ajax call and each partial view usage javascript and include js file, which eventually calls database to bind the data for that particular view.
Now, loading the view is taking more time than expected, as it loads js file and that js file makes another call to server to pull the records. I want my view to be loaded and then js file which makes db call to bind data. something like below -
If(partialview is loaded)
load js file , which will make ajax call and db eventually to bind data.
This will at least load the view and user will have something to see instead of waiting for blank background with loader.
Below is the script through which i am loading PartialView.
function loadview(action, hassubmenu, _fromtab) {
if (hassubmenu == 'true') {
return false;
}
if (!_fromtab) {
$('.process').show();
$('.mainbody').html('');
}
// call ajax to load view
$.ajax({
url: urlheader + "Home/LoadView/",
type: 'POST',
data: {
'view': action
},
success: function (data) {
// This outputs the result of the ajax request
$('.process').hide();
if (!_fromtab) {
$('.mainbody').html('').html(data);
// disable appfilter from start screen
var ostype = $('select#selection').find('option:selected').data('ostype');
var did = $('select#selection').find('option:selected').val();
if (ostype.toLowerCase() == 'ios' && action == 'Start') {
$('div.appfilter').hide();
$('#liAppFilter').hide();
}
getsyncinfo(did, false);
if (_currenttab != undefined) {
reloadCurrentFilterTab(_currenttab);
}
}
else
$('.chicoAppsUrlsDetails').html('').html(data);
},
error: function (errorThrown) {
console.log(errorThrown);
}
});
}

If I understand correctly, js events aren't firing for html inside your partial views (those of which are ajaxed)
This is because the html being loaded onto the page is coming after the js (which is binding your events).
You need to place any events on doms inside the partial view onto the document element instead with the jquery on method to specify a selector.
eg.
$(document).on('click', '.some-class', function(){
//do stuff
});
this way, you can add partials to the page with ajax and the doms within the partial will still fire events.

Related

Transferring info from view to Controller

I'm working on an asp-mvc application and facing the following issue:
I have a model with simple properties plus one property which is a list of my custom object, and I render the Ienumerable property as mentioned here:
Passing IEnumerable property of model to controller post action- ASP MVC
In my view, I have a button that is supposed to add items to the ienumerable property of my model. Of Course, I don't want to lose already inserted data, so I need to pass the model to the corresponding action.
I've noticed that the model os transferred entirely only upon post. So, I did something like:
$(".addButton").click(function (event) {
event.preventDefault();
$("#FilterForm").submit();
#{ Session["fromAddFullItem"] = "true";}
return false;
});
And then in my controller, I do something like:
public ActionResult Index(FilterModel model)
{
if (Session["fromAddFullItem"].ToString() == "true")
{
Session["fromAddFullItem"] = "false";
return AddBlankItemTemplate(model);
}
I've read that assigning session in js is not recommended, but also tried TempData, and there the data was always null.
My problem is that Session["fromAddFullItem"] is always true, even when I come from another button. If I put breakpoint in addbtn click in line- Session["fromAddFullItem"] = "false";, and press the other button, I see that for some odd reason the mentioned breakpoint is hit, even though I haven't pressed the add button.
Any help? Maybe there is another way to achieve what I want. Currently, no matter which button I press (which posts the form), it comes as Session["fromAddFullItem"] = "false" and goes to action AddBlankItemTemplate. Thanks.
EDIT - AJAX POST
$(".addButton").click(function(event) {
event.preventDefault();
var modelData = JSON.stringify(window.Model);
$.ajax({
url: '#Url.Action("AddBlankItemTemplate")',
type: 'POST',
dataType: 'json',
data: modelData,
contentType: 'application/json; charset=utf-8',
});
return false;
});
and controller
public ActionResult AddBlankItemTemplate(string modelData)
EDIT 2:
$(".addButton").click(function (event) {
event.preventDefault();
$.ajax({
url: '#Url.Action("AddBlankItemTemplate")',
data: $("#FilterForm").serialize()
}).success(function(partialView) {
$('DetailsTemplates').append(partialView);
});
});
and Controller:
public ActionResult AddBlankItemTemplate(FilterModel model)
The line #{ Session["fromAddFullItem"] = "true";} is Razor code and will be run on page rendering and load regardless of where you put it in the page.
It's not client side code so won't wait for your js code to run. If you're trying to synchronise state between js and MVC have you looked into angularjs which could simplify these actions.

Ajax call gets cached, despite the appropriate parameter

I'm currently writing a MVC C# application. Everything works just fine. I have a bit of functionality, where I fill up a Bootstrap modal box using an Ajax call, but the new page gets cached, despite my efforts to prevent that.
On my main page I have the following actionhandler to fill up the modal box:
function setExtraPermsOrAtts(appID){
$.ajax({
cache:false,
url: "/Group/_modifyAppPermissionsOfGroup?appID=" + appID
}).done(function (result) {
$("#addApplicationBody").html(result);
$('#modal-add-application').modal('show');
});
}
This gets caught by the following method:
public ActionResult _modifyAppPermissionsOfGroup(int? appID = 0)
{
if (appID != 0)
{
ViewBag.selectedAppID = appID;
Session["selectedGroupAppID"] = appID;
ViewBag.modifyPermsLater = true;
}
Group group = (Group)Session["currentGroup"];
return View(group);
}
Another thing that might be relevant is the point where it 'goes wrong'. The resulting View in the Modalbox, has a few radio buttons, depending on the content of the database. There I do a razor statement to get the DB value:
bool valueOfRadButtons = BusinessLogic.Domain.GroupIS.getExistingGroupPermission(
Model.LoginGroupID, myItem.ApplicationPermissionID).LoginPermissionState;
Does anyone know where I'm going wrong? Is it the Ajax call? The ActionResult method in the Controller? Or the inline razor statement? I know the data gets saved properly, cause I see so in the DB
You can specify that the response shouldn't be cached like this:
Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
Response.Cache.SetValidUntilExpires(false);
Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
It can be more easy if you make your own attribute and decorate the action with it as shown here.

Redirect after Ajax

I have a mvc project, what I want to do is this:
I am sending an ajax request from my JS script. After processing it I want to redirect to a page with a model.
Now I tried sending a form as the ajax response and submit it like so:
sb.Append("<html>");
sb.AppendFormat(#"<body onload='document.forms[""form""].submit()'>");
sb.AppendFormat("<form name='form' action='{0}' method='post'>", "url..");
sb.AppendFormat("<input type='hidden' name='result' value='{0}'>", val1);
.....
And on the JS:
success: function (result) {
var form = $(result);
$(form).submit();
}
But this way i need to specify each post param, I want to send the entire model object.
How can I do that?
Edit
Full steps:
1.Using an MVC APP.
2.I submit button in my view which redirects the user to my JS code.
3.Js code sends an Ajax request to a MVC page called 'Transaction'.
4.C# code doing some actions and now I need to redirect the usr to a page named EOF with ALOT of post params, thats why I want to pass it as a ViewModel.
As you are using ajax, you could return the URL from your action and have it redirected in javascript:
Controller
public ActionResult Transaction()
{
// Do stuff
return Json(new { success = true, redirecturl = Url.Action("RedirectedAction") });
}
Then add something like this to your success handler in javascript:
Javascript (within your success handler)
success: function (result) {
if (result.success == true)
{
window.location = result.redirecturl;
}
}
You can try this:
public ActionResult YourMethod(string param)
{
//what ever you want to do with reference no
return View("EOF");
// or, if you want to supply a model to EOF:
// return View("EOF", myModel);
}

Using jquery to render html from an action within an area

I have a jquery click method that looks like this
<script type="text/javascript">
function clickView(e) {
e.preventDefault();
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
$.ajax({
url: "/Jac/ViewCustomDetails",
data: { productId: dataItem.Id },
success: function (response) {
$("#details").html(response);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
document.write(xhr.responseText);
}
});
}
</script>
Basically this makes an AJAX call to my controller to render an action.
The action ViewCustomDetails, which is within JacController, and within an area looks like this:
public ActionResult ViewCustomDetails(int productId)
{
Detail model;
model = new Detail
{
Price = productId.ToString(),
Origin = productId.ToString()
};
return View(model);
}
When I click on my button that fires off the AJAX call, I am able to break into my action. however I get this error in my view
The view 'ViewCustomDetails' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Jac/ViewCustomDetails.aspx
~/Views/Jac/ViewCustomDetails.ascx
~/Views/Shared/ViewCustomDetails.aspx
~/Views/Shared/ViewCustomDetails.ascx
~/Views/Jac/ViewCustomDetails.cshtml
~/Views/Jac/ViewCustomDetails.vbhtml
~/Views/Shared/ViewCustomDetails.cshtml
~/Views/Shared/ViewCustomDetails.vbhtml
Obviously there's no such controller/action in my views folder as my controller is within an area.
How do I get it to reference the controller in my area?
It IS referencing your controller but the line return View(model); in your ViewCustomDetails method requires the existence of a View file, which would normally be called ViewCustomDetails.cshtml
This View file must take a model type of Detail
You might also need to JSONify the returning view.
I just had to add the area name into my URL in the jquery code as such
url: "/Dan/Jac/ViewCustomDetails",
instead of just
url: "/Jac/ViewCustomDetails",

The best approach to send data to a Partial View Model and .html() being slow

Imagine I have a Partial View with a list of users ( loop ) where each user is another partial view with details about one.
foreach (var user in Model.Users)
{
<a href="#" onclick="JavascriptFunction(user.Id);">Details<a>
}
When I click the above Details link for one of the list items a popup (JQuery modal dialog() ) pops up with details about that selected user. Or at least that's the goal. I need to get the selected user details to a new popup that opened.
So now I need to populate the model behind the partial view that the popup will contain with user details before .dialog('Open') triggers.
Question: What's the best way, from within a Javascript function ( onclick JavascriptFunction function in the example above) to call an ActionMethod and populate the Partial View model before the dialog is displayed ?
Right now I'm doing it the following way but for whatever reason I'm getting major delays in data being rendered on the page. I see blank div for good 5-10 seconds before .html() finally displays data:
On the main list page:
<div id="userPopup"></div>
Javascript that suppose to load Partial view with User details from an ActionMethod:
$.post('#Url.Action("Details","User")', { id: userId},
function (data) {
$("#userPopup").html(data);
});
Possibly there is a way to pre-load a partial view on the page and then just load my data into its Model without re-writing the entire PartialView ?
That would be the ideal scenario but I don't think there is a way to do it, is there ?
Thank you in advance ! Don't hesitate to ask questions if anything sounds confusing.
I dont think you should preload all the user details on the main page, what if you have 1000+ users and the visitor is not clikcking the details link ! I would do it in this way. Whenever user clicks on the link, make a call to an action method which returns the data.
So in your main view,
#foreach(var user in Model.Users)
{
#Html.ActionLink(user.Name, "Details", "User",
new { Id = user.ID, }, new { #class ="popupLink" })
}
<script type="text/javascript">
$(function(){
$(".popupLink").click(function (e) {
e.preventDefault();
var url = this.href;
var dialog = $("#dialog");
if ($("#dialog").length == 0) {
dialog = $('<div id="dialog" style="display:hidden"></div>').appendTo('body');
}
dialog.load(
url,
{}, // omit this param object to issue a GET request instead a POST request, otherwise you may provide post parameters within the object
function (responseText, textStatus, XMLHttpRequest) {
dialog.dialog({
close: function (event, ui) {
dialog.remove();
},
modal: true,
width: 460
});
}
);
});
});
</script>
In User controller, have an action method called "Details which accepts the Id as parameter and return the View of User details
public ActionResult Details(int id)
{
var usre=repositary.GetUser(id);
return View(user);
}
Have your HTML markup for details in the DetailsView.
This code use jQuery UI model dialog. So you need to include that.

Categories