I am creating an umbraco MVC page that has a template that renders a partial view with 2 dropdown lists and a google map. When i load the page it has the master template with a partial view and it shows everything fine.
When i select an item from the dropdown list i pass the value to the controler and return to the partial view other data. The problem is that the return of the partial view shows only the partial view without the master template.
This is the code in the controller that fires when the page is loaded for the first time and this shows everything:
public ActionResult RenderForm()
{
MapFunction MF = new MapFunction ();
MF=SetDropDown();
MF.JSON= SetMarkers();
return PartialView(Partial_View_Folder + "_MapFunction .cshtml", MF);
}
This is the code that fires when the dropdown is selected:
public ActionResult ChangeATM(MapFunction mapFunction)
{
MapFunction MF = new MapFunction ();
mapFunction= ddlATMChange(mapFunction.PTT.ToString());
MF = SetDropDown();
mapFunction.Branch = MF.Branch;
mapFunction.ATM = MF.ATM;
return PartialView(Partial_View_Folder + "_MapFunction.cshtml", mapFunction);
}
My partial view code with the ddl:
#using (Html.BeginUmbracoForm("ChangeATM", "MapFunction", FormMethod.Post))
{
#Html.DropDownListFor(m => m.PTT, Model.Branch, "Chose...", new { onchange = "this.form.submit();" })
}
I just want to refresh the partial view without loosing my master page and with new data.
The problem was the BeginUmbracoForm in the PartialView.
I changed it to:
#using (Ajax.BeginForm("ChangeATM", "MapFunction", null, new AjaxOptions
{
HttpMethod = "Post",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "Parent"
}))
{
#Html.DropDownListFor(m => m.PTT, Model.Branch, "Choose...", new { onchange = "$(this.form).submit();", id = "use-ajax1" })
}
Also you need to add the folowing script to the master page:
<script type="text/javascript">
$(document).on("change", ".use-ajax1", function (e) {
e.preventDefault();
var form = $(this).closest('form');
$(form).submit();
});
The script prevents default actions and submits form using AjaxCall.
Related
I'm making a post request from on view so that I don't see the parameters on the URL and I can tell it is passing the appropriate parameters to controller for the request but it does not display the appropriate view from that controller.
Calling view
#Ajax.ActionLink("Work1", "NewIndex", "WorkItems",
new
{
eventCommand = "createforrig",
//eventArgument1 = #item.Id,
eventArgument2 = #item.Id
},
new AjaxOptions
{
HttpMethod = "POST"
})
WorkItems Controller method
[HttpPost]
public ActionResult NewIndex(NewWorkItemViewModel vm)
{
vm.IsValid = ModelState.IsValid;
vm.HandleRequest();
if (vm.IsValid)
{
// NOTE: Must clear the model state in order to bind
// the #Html helpers to the new model values
ModelState.Clear();
}
else
{
foreach (KeyValuePair<string, string> item in vm.ValidationErrors)
{
ModelState.AddModelError(item.Key, item.Value);
}
}
return View(vm);
}
Putting a breakpoint on the last Return View(vm) confirms it is being called but the browsers does not update to display the workItems view.
Suggestions on why the browser is not being updated to display the appropriate view.
You're making an ajax post, the newly rendered view is being returned by the server if you were to look in the network console in your browser. Add a success callback. Either assign a callback to handle the response or use the
UpdateTargetId property in your AjaxOptions
#Ajax.ActionLink("Work1", "NewIndex", "WorkItems",
new
{
eventCommand = "createforrig",
//eventArgument1 = #item.Id,
eventArgument2 = #item.Id
},
new AjaxOptions
{
HttpMethod = "POST",
OnSuccess = "AjaxSuccess", //handle with callback
UpdateTargetId = "MyElementID" //update html element
})
if you choose to use OnSuccess then in javascript
function AjaxSuccess(data){
//handle response
}
AjaxOptions properties and usage can be found here
EDIT
You could use javascript to submit a form when a link is clicked, put a form somewhere in your code and hide it.
#using (Html.BeginForm("NewIndex", "WorkItems", FormMethod.Post,
new { class = "hidden", id = "postForm" } ))
{
<input type="hidden" name="eventCommand" value="createforrig" />
<input type="hidden" name="eventArgument2" value="#item.Id" />
<input type="submit" value="link text" id="submitForm"/>
}
then change your #Ajax.ActionLink... to
#Html.ActionLink("Work1", "NewIndex", "WorkItems", new { id = "postLink"})
and if you're using jQuery
<script>
$(function(){
$('#postLink').click(function(e)
{
e.preventDefault();
$('#postForm').submit();
});
});
</script>
and don't forget to hide the form in css
.hidden { display:none;}
This is my link to a partial view:
#Ajax.ActionLink("All", "All", "Products", new { id = Model.id_product }, new AjaxOptions()
{
HttpMethod = "GET",
UpdateTargetId = "divImages",
InsertionMode = InsertionMode.Replace
})
<div id="divImages"></div>
and here's the method being invoked and returns the partial view:
public PartialViewResult All(int id)
{
List<Image> model = db.Images.Where(x => x.id_product == id).ToList();
return PartialView("_File", model);
}
I want my partial view to be loaded immediately after the main view loaded instead of the link to the partial view. How can I do that?
To render a partial view generated by a controller method in the main view, use #Html.Action() or #{ Html.RenderAction(); }
#{ Html.RenderAction("All", "Products", new { id = Model.id_product }); }
This is pretty much my third day developing MVC and I have what I hope will be a simple question. Basically I have a WebGrid within a partial view, which has a column that performs an update via a controller.
The controller then returns the updated partial view successfully, but the it replaces the whole page with the results instead of just the partial view.
Here's the partial view:
#model Site.Models.UsersForCompanyModel
#{
ViewBag.Title = "Admin User Management Grid";
}
#{
var grid = new WebGrid(
Model.Users,
ajaxUpdateContainerId: "divUserGrid",
fieldNamePrefix: "gridItems_",
pageFieldName: "paging",
sortFieldName: "sortField"
);
grid.Pager(WebGridPagerModes.All);
var userColumns = new List<WebGridColumn>
{
new WebGridColumn {ColumnName = "Email", Header = "E-Mail", CanSort = true},
new WebGridColumn {Header = "Lock", Format = user => user.isAdmin ? Html.Raw("n/a") : Html.ActionLink(user.IsLocked ? "Unlock" : "Lock", "ToggleLock", new {userId = user.Id, companyId = Model.CompanyId}) },
};
<div id="divUserGrid">
#grid.GetHtml(
htmlAttributes: new { id = "userGrid" },
tableStyle: "table table-striped table-bordered",
columns: userColumns
)
</div>
}
...and here's the controller code:
public ActionResult GetUsersForCompany(string companyId)
{
using (var service = new ManagementService())
{
var model = GetUsersForCompany(companyId, service);
return PartialView("AdminUserManagement_Grid", model);
}
}
public ActionResult ToggleLock(string companyId, string userId)
{
using (var service = new ManagementService())
{
var user = service.GetUserById(userId);
service.LockUser(userId, !user.IsLocked);
return GetUsersForCompany(companyId);
}
}
What's the easiest way to go about updating the partial view with the results returned from ToggleLock()?
Is there a way to do it declaratively via Html.ActionLink or Ajax.ActionLink?
The easiest way is to put your partial view in container div like below
<div id="PartialViewDivId">
#{ Html.RenderAction("GetUsersForCompany",model.CompanyId);}
</div>
Then use jQuery to load the updated view
On some click event
var companyId= read company id
var userId= read user id
var url = "mycontroller/ToggleLock?companyId="+companyId+"&userId"+userId;
$("#PartialViewDivId").load(url)
Thanks, Kartikeya. Partial credit for the answer, though I found a declarative way that didn't require manual HTML/event wiring and custom javascript.
The key was simply switching to an Ajax.ActionLink (instead of using Html.ActionLink), then setting my partial view placeholder ID (I had a div setup similar to Kartikeya's example) and a few other parameters in the AjaxOptions of the control, like this:
new WebGridColumn {Header = "Lock",
Format = user => user.isAdmin ? Html.Raw("n/a") :
Ajax.ActionLink( user.IsLocked ? "Unlock" : "Lock",
"ToggleLock",
new{userId = user.Id, companyId = Model.CompanyId },
new AjaxOptions
{
UpdateTargetId="userGridPlaceholder", // <-- my grid placeholder
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET"
})
Im developing an MVC project and im using Ajax for displaying a list of shifts.
Here's my parent page, shifts.chtml:
#model UI.ViewModels.ViewModelShiftList
<h2>Shifts</h2>
#Ajax.ActionLink("View All Shifts", "AllShifts", "Shifts",
new AjaxOptions
{
UpdateTargetId="searchResults",
HttpMethod="GET", //default
InsertionMode= InsertionMode.Replace, //replace
LoadingElementId="progress"
})
<div id="searchResults">
#Html.RenderPartial("_ShiftList",model)
</div>
heres the controller action for the above page:
public ActionResult Shifts()
{
ViewModelShiftList viewModel = new ViewModelShiftList
{
Shifts = _shiftService.GetShifts().ToList()
};
return View(viewModel);
}
Should I not be able to send the viewmodel produced here into the partial view? Or do I have to create another action for the partial view? If so, what is the correct way to send an action to the controller of a partialview?
The error im gettin is at this point:
#Html.RenderPartial("_ShiftList",model)
// cannot impilicty convert type void to object
This was a simple fix...I needed to add curly brackets like so..
#{Html.RenderPartial("_shiftlist", Model);}
Problem
I have Telerik TabControl and each tab content is a partial view. Everything works smoothly when request is GET:
//
// GET: /ProductVersion/Translations
public ActionResult Translations(Guid id)
{
VersionEditTabViewModel model = CreateTranslationsViewModel(id);
return PartialView("Translations", model);
}
Now the problem is that on some tabs I have a Form that has controls that trigger submit event.
[HttpPost]
public ActionResult Translations(Guid id)
{
FormCollection formCollection = new FormCollection(Request.Form);
string message = string.Empty;
int languageId = int.Parse(formCollection["TranslationsLanguageList"]);
string action = formCollection["TranslationAction"];
if(action == Constants.translation_save)
{
_translationModel.SaveTranslations(formCollection);
message = "Translation information saved";
}
else if (action == Constants.translation_language_changed)
{
/*
PROBLEM: causes whole page to render, not partial
*/
return PartialView("Translations", model);
}
return RedirectToAction( ... updates the complete page not only partial ...);
}
My question is: how to render partial from the POST method? Because now with that source code tab content will be loaded to the WHOLE page, not inside tab.
Solution
I had to put DIV outside of the Ajax.Form and also I had incorrect submit on my DropDownList. What I did was that I created hidden submit button with Id and then I used jQuery to execute it's click event.
For additional reference, please refer to this question on SO:
MVC - Using Ajax to render partial view
This shows a complete implementation of the Ajax.BeginForm with surrounding DIV and inner form controls. You should be able to place this entire setup (DIV + Form + HTML Form Elements) in the Telerik Tab, like this:
<% Html.Telerik().TabStrip()
.Name("TabStrip")
.Items(tabstrip =>
{
tabstrip.Add()
.Text("Your Tab Text")
.Content(() =>
{%>
<div id="containerDiv" align="left">
<% using (Ajax.BeginForm("Example", "Controller/Action", new AjaxOptions { UpdateTargetId = "containerDiv" })){ %>
<%-- Render Partial here -->
<% } %>
</div>
<%});
Hope that helps.
I did my trough ajax form:
using (Ajax.BeginForm("*ActionName*", new { *parameter = ID* }, new AjaxOptions { UpdateTargetId = (*div i will update*), OnSuccess = "*JavaScript that executes on success*", OnComplete = "s*ame as on success*", InsertionMode = InsertionMode.Replace }))
and then i have
return PartialView("*PartialViewName*", model);
in post Action
And it works just fine, on post, action returns partial view and then ajax form replaces the content of the div specified in the UpdateTargetId with InsertionMode.Replace