Updating a Partial View From A Link In Its Own WebGrid - asp.net-mvc

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

Related

MVC partial view renders without master page

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.

Update DropDownListFor data source from controller MVC

I have a DropDownListFor that takes data source from controller. Is there a way to update it since i'm adding new values that i want then to be displayed on the same page.
View:
#Html.DropDownListFor(m => m.Id, MyController.GetIds(Model.Id).Select(g => new SelectListItem { Text = g.Text, Value = g.Value }), #Resource.System_Choose, new
{
#class = "form-control selectpicker",
data_live_search = "true"
})
Controller:
public static List<SelectListItem> GetIds(int Id)
{
var retVal = new List<SelectListItem>();
return retVal;
}
Make your View deal with Model that has property of type List<SelectListItem>() and return this property ready to be binded and displayed in DropDown.
There are some ways to achieve the goal,
Use only javascript to append the new value to select options. (If the new value doesn't send to backend)
Ajax and get the new list.
A sample for case 2, we can put the DropDownList to a partialview and use ajax to get the latest DropDownList in the partialview.
Controller :
public ActionResult QueryNewList()
{
return PartialView("~/Views/Home/_urPartialView.cshtml", viewModel);
}
Html:
<div id="myDiv"></div>
Js:
$.ajax({
dataType: "html",
url: "QueryNewList",
success: function (html) {
$("#myDiv").html("");
$("#myDiv").append(html);
}
})

asp.net mvc fill a dropdownlist according to the item selected in an author

i'm a total beginner in asp.net mvc and am trying to change the items in a dropdownlist according to the item selected in an author one (they are filled from a database)
<% using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "TheForm" }))
{
Filiere: <%= Html.DropDownList("filiere", (SelectList)ViewData["filiere"], new { onchange = "this.form.submit();" })%>
Module:<%= Html.DropDownList("module",(SelectList)ViewData["module"])
}
%>
public ActionResult Index(int? fil)
{
var fi = db.filiere.Select(f => new {f.id,f.nom });
ViewData["filiere"] = new SelectList(fi.AsEnumerable(), "id", "nom");
List<module> mod;
if (fil == null)
mod = db.module.ToList();
else
{
mod = (from module in db.module
where module.id_filiere == fil
select module).ToList();
}
ViewData["module"] = new SelectList(mod.AsEnumerable(),"id","nom");
return View();
}
Try to create one more method in controller who accept the author information and return the list which you want to display in drop-down.
then simply put ajax call on author change event call the controller method for data and also pass current author information and on success bind result what you get from controller method to drop-down.

handle 'open in a new window' when clicked on ajax.ActionLink which point to action that returns partial view

Hello I've got an action which gets some data from database and returns a partial view
In the partial view there are ajax.actionLinks which when clicked execute the same ImportShow action but this time with new data; and as you see in the cshtml - then update only the with the new data.
The problem I'm trying to solve is - if a user clicks 'Open in new Window' or 'open in new tab' in the new window you will see loaded only this partial view. And I can't think of a way how to make redirect and reload the whole page only in this cases. (after all the link point to an action method that RETURNS A PARTIAL VIEW).
public virtual ActionResult ImportShow(String id, String menuID, string articlegroupID, int? counter)
{
GroupMenu p_GroupMenu = new GroupMenu();
p_GroupMenu.MenuHistory = p_GetMenuHistory.ToList();
p_GroupMenu.MenuLeft = p_GetMenuLeft.ToList();
return PartialView("ImportShow", p_GroupMenu);
}
As
model MvcBeaWeb.GroupMenu
<div class="importPartUpdate">
<ul id="products">
#{
if (Model != null)
{
foreach (MvcBeaDAL.WebServiceBeaMenu item in Model.MenuLeft)
{
<li id="#item.ID">
<div class="imageTilesShow">
<a title= #item.SpecialWord>
<img src="#item.ImageFile" alt='#item.SpecialWord)' id="ImageProducts" class="imageTilesShow">
#Ajax.ActionLink(#item.SpecialWord, "ImportShow", new { id = Model.LanguageName,menuID=#item.ID},new AjaxOptions { UpdateTargetId = "importPartUpdate", HttpMethod = "GET", InsertionMode = InsertionMode.Replace })
</a>
</div>
</li>
}
}
}
</ul>
</div>
There are a few posts that having this issue before, you can check out this and this. Basically what happens is: when you click the "ajax" link, it is a AJAX call, therefor the partial view was rendered and everything works as expected. However, when you right click to view the page a new tab or new window in the browser, it is NOT a AJAX call, but you're returning a partial view, the new tab or window will still return a partial view. That's why you only see the partial view.
To illustrate what I meant:
here's the code snippet.
public class HomeController : Controller
{
List<Person> people = new List<Person>()
{
new Person { Name = "Larry", Age = 10},
new Person { Name = "Jessie", Age = 11},
new Person { Name = "Ben", Age = 12},
new Person { Name = "Victor", Age = 13},
new Person { Name = "Tom", Age = 14},
new Person { Name = "Suresh", Age = 15},
new Person { Name = "Jim", Age = 16},
};
public ActionResult Index()
{
return View();
}
public ActionResult GetPerson()
{
Random r = new Random();
int i = r.Next(0, people.Count);
if (Request.IsAjaxRequest())
{
return PartialView(people[i]); //return partial if it's a ajax call
}
else
{
return View(people[i]); // return view if it's NOT a ajax call
}
}
}
Index View:
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Ajax.ActionLink("replace", "GetPerson", new AjaxOptions { UpdateTargetId = "replaceMe", HttpMethod = "Get", InsertionMode = InsertionMode.Replace})
<div id = "replaceMe"></div>
Partial View:
#model MvcApplication1.Controllers.Person
<div>
Name : #Model.Name <br />
Age : #Model.Age
</div>

Update drop down using Ajax.ActionLink

I am trying to update the dropdown list:
View:
<div class="editor-field">
Names: <%: Html.DropDownList("names", (SelectList)ViewData["Names"]) %>
<%:Ajax.ActionLink("Refresh", "GetNames", new AjaxOptions { UpdateTargetId = "names", HttpMethod = "GET" })%>
</div>
Controller:
[HttpGet]
public ActionResult GetNames()
{
List<String> names = this.GenerateNames();
return Json(new SelectList(names));
}
The flow is the following: when user makes the first request, the list is updated from viewdata, then user presses refresh and the dropdown is populated usin ajax request.
I tried to return both JSON result - the dropdown is not updated. When returning SelectList the dropdown just gets cleared.
How can I accomplish this task?
You could put this drop down into a partial (Names.ascx):
<%# Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<YourApp.Models.SomeViewModel>" %>
Names: <%: Html.DropDownList(x => x.SelectedName, Model.Names) %>
And then in your main view use this editor template:
<div class="editor-field">
<span id="names"><% Html.RenderPartial("Names"); %></span>
<%: Ajax.ActionLink("Refresh", "Names",
new AjaxOptions { UpdateTargetId = "names", HttpMethod = "GET" }) %>
</div>
And you controller action could look like this:
public ActionResult Names()
{
var model = new SomeViewModel
{
// TODO: fetch the names from db:
Names = new SelectList(new[] {
new { Id = "1", Text = "name 1" },
new { Id = "2", Text = "name 2" },
new { Id = "3", Text = "name 3" },
}, "Id", "Text")
}
return View(model);
}
Just update the viewdata again so the view can use the same code to update itself for the second shot, being the Ajax return. And u don't need to use Json for that. Let me know how it goes.

Resources