How to do a partial view on ActionLink - asp.net-mvc

<table>
<tr>
<th>
Author
</th>
<th>
Title
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Author)
</td>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
#Ajax.ActionLink("View Reviews", "View", new { id = item.ID }, new AjaxOptions { UpdateTargetId = "result", InsertionMode = InsertionMode.InsertAfter })
</td>
</tr>
}
</table>
<div id="result">
</div>
public PartialViewResult View(int id)
{
ReviewModel reviewModel = new ReviewModel();
return PartialView(reviewModel.GetReviews(id));
}

Once the response has been sent to the client, the server is done. That means you can't directly have a partial view rendered based on a click, because those are two disjointed processes: a partial view is rendered server-side, while a click is registered client-side, once the server is already out of the picture.
Anytime you're talking about changing the already rendered page in client with some new information from the server, you're talking about AJAX, so you will need to handle that with JavaScript on the client-side, that catches the click event and requests the partial view from the server. That means you'll also need an action, server-side that your JavaScript can send a request to and that returns your partial view.
ReviewsController
public ActionResult View(int id)
{
// fetch reviews for `id`
if (Request.IsAjaxRequest())
{
// return partial for AJAX requests
return PartialView("_ReviewsPartial", reviews);
}
else
{
// return full view for regular requests
return View(reviews);
}
}
Main View
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Author)
</td>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
#Html.ActionLink("View Reviews", "View", new { id=item.ID }, new { #class = "GetReviewsLink", data_id = item.ID })
</td>
</tr>
}
<div id="SomeDiv"></div>
JavaScript
$(document).ready(function () {
$('.GetReviewsLink').on('click', function (e) {
e.preventDefault();
var id = $(this).data('id');
$.get('#Url.Action("View")', { id: id }, function (result) {
$('#SomeDiv').html(result);
});
});
});
That will dump the rendered partial from the server into the div with id, "SomeDiv". You can then display it however you want. For example, you may have a static region that will just switch out the reviews as each item's link is clicked. "SomeDiv" may actually be the inner part of a modal window, that you could then show after the new content has been loaded in. However you want to handle the display.

Related

.NET MVC JQuery function is not getting fired in table row click event

I have table data in UI. I want to display data in a div in the same page when I click the Details link in the row. The JQuery function is not getting fired in when I click on details link in any row.
Below is my code:
Model view class:
public class ItemViewModel
{
public Item item { get; set; }
public IEnumerable<Item> items { get; set; }
}
UI Code:
#model Medhub.Models.ItemViewModel
#{
ViewBag.Title = "View";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>View</h2>
<p>
#Html.ActionLink("Create New", "CreateEdit", new { controller = "Item" }, new { #class = "btn btn-primary" })
</p>
<table align="center" height="10%" width="90%">
<tr>
<td>
<div id="Items">
<table style="vertical-align:top; height:200px" width="100%">
<tr style="height:20px">
<th>
#Html.DisplayName("Name")
</th>
<th>
#Html.DisplayName("Description")
</th>
<th>
#Html.DisplayName("Item Type")
</th>
</tr>
#if (Model != null)
{
foreach (var item in Model.items)
{
<tr style="height:15px">
<td>
#Html.HiddenFor(model => item.ItemId)
#Html.DisplayFor(model => item.Name)
</td>
<td>
#Html.DisplayFor(model => item.Description)
</td>
<td>
#Html.DisplayFor(model => item.Type)
</td>
<td>
#Html.ActionLink("Edit", "CreateEdit", new { id = item.ItemId }) |
#Html.ActionLink("Details", "Item", new { id = item.ItemId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.ItemId })
</td>
</tr>
}
}
</table>
</div>
</td>
</tr>
</table>
<table>
<tr>
<td>
<div id="ItemDetails">
#if (Model.item != null)
{
Html.RenderPartial("Details", Model.item);
}
</div>
</td>
</tr>
</table>
<script type="text/javascript">
$(function () {
$("div.Items a").click(function (e) {
//e.preventDefault();
var url = this.ref;
$("#ItemDetails").load(url);
});
});
</script>
Controller code:
List<Item> items = new List<Item>();
// GET: Item
public ActionResult Item(int id = 0)
{
ItemViewModel itemVM = new ItemViewModel();
itemVM.items = GetItems();
if (id > 0)
itemVM.item = itemVM.items.FirstOrDefault(u => u.ItemId == id);
return View(itemVM);
}
Any clues?
First of all, you are waiting for clicks on a class called Items. This is the reason the jquery code is not being fired. You should have
$("div#Items a").click(function (e) {
Secondly, you need to check the attribut href, not ref. Also, prevent default needs to be there, otherwise you just reload your page
e.preventDefault();
var url = this.href;
You don't need the renderpartial in the page, just leave it empty:
<div id="ItemDetails">
</div>
While your logic kind of works, the way the url is loaded causes the entire page to be loaded into the ItemDetails section. I'd suggest that in your controller, you'd create a separate method for the details:
public ActionResult Details(int id) {
Item item = GetItem(id);
return View(item);
}
private Item GetItem(int id) {
return new Item() { Details = "details here" };
}

How to highlight a new added entry in MVC?

I've created a DB application in MVC 4 using EntityFramework. It works okay, however I couldn't find the way of highlighting new added item to my table(html). Is it possible to highlight new rows in DB applications in MVC? Like in C#:
DataGrid.SelectedItem
Any advice or help would be very clarifying. How to highlight a row in MVC?
How are you rendering the table?
One option is to use TempData. Store the identifier of the added item in TempData and check for the identifier when rendering the table.
ItemController:
// POST: /Item/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include="Id,Name")] Item item)
{
if (ModelState.IsValid)
{
db.Items.Add(item);
db.SaveChanges();
TempData["AddedItemId"] = item.Id;
return RedirectToAction("Index");
}
return View(item);
}
Item view:
<!-- Views\Item\Index.cshtml -->
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
var className = "";
if (TempData["AddedItemId"] != null && (int)TempData["AddedItemId"] == item.Id)
{
className = "alert-info";
}
<tr class="#className">
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>

Regarding return view with model usage

i am new in mvc. i have got a code where view is returning with model. what does it mean.
if i return view with model then model data can be access from view.
public ActionResult GetView(int id)
{
switch (id)
{
case 1:
return View("View1", model1);
break;
case 2:
return View("View2", model2);
break;
default:
return View("Default", modelDefault);
}
}
i need to see a small complete example where view will be return with model and view will be populated with model data. can anyone redirect me to a good example on this topic. thanks
Here you have a sample
CONTROLLER
public ActionResult Index()
{
// return a list of movies to view
return View(db.Movies.ToList());
}
VIEW
//declare expected type of model, if view returns something else, it will fail
#model IEnumerable<MvcMovie.Models.Movie>
//use model sent from controller
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<th>
#Html.DisplayFor(modelItem => item.Rating)
</th>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", { id=item.ID })
</td>
</tr>
}
More information on Accessing Your Model's Data from a Controller

Postback model is null

I changed my index view so that each row is wrapped in a form:
Index.cshtml
#model IEnumerable<LevEl.Models.Page>
#foreach (var item in Model)
{
using (Html.BeginForm("Edit", "Pages", item, FormMethod.Post, new { id = "itemForm_" + item.PageId }))
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
...
... more fields
...
<td>
#Html.CheckBoxFor(modelItem => item.IsPublished, new { onClick = "$(itemForm_" + item.PageId + ").submit();" })
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.PageId }) | #Html.ActionLink("Details", "Details", new { id = item.PageId }) | #Html.ActionLink("Delete", "Delete", new { id = item.PageId })
</td>
</tr>
}
}
Here's my controller:
PagesController.cs
public ActionResult Index()
{
return View(db.Pages.Include(p => p.Language).ToList());
}
[HttpPost]
public ActionResult Edit(Page page)
{
var method = Request.HttpMethod;
if (ModelState.IsValid)
{
if (page.PageContents.GroupBy(pc => pc.Language).Any(g => g.Count() > 1))
return HttpNotFound("A page cannot have two translations in the same language.");
db.Entry(page).State = EntityState.Modified;
db.SaveChanges();
ClearMenuKeys();
return RedirectToAction("Index");
}
return View(page);
}
When I switch the value in the check box and the controller is reached, page is null.
How can I pass the entire page object upon postback?
It seems to me like your HTML do not store values of the Page. #Html.DisplayFor only displays data you have to set #Html.HiddenFor for that field too.
EDIT:
#Html.DisplayFor(modelItem => item.Title)
#Html.HiddenFor(modelItem => item.Title)

asp.net mvc viewdata to display category name

I am using ado.net entity model from an existing database.
I am using two tables products and categories.
I have a product controller:
public ActionResult Products()
{
using (var db = new StoreMvcEntities())
{
ViewData["categories"] = db.Categories.ToList();
return View(db.Products.ToList());
}
}
and a view:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ProductName)
</td>
<td>
#Html.DisplayFor(modelItem => item.category.categoryname)
</td>
<td>
#Html.DisplayFor(modelItem => item.price)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Details", "Details", new { id=item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
Here is the problem: in the controller, if I remove the ViewData["categories"] = db.Categories.ToList(); the product category name is empty in the view. I'm not using the ViewData["categories"] in the view, and to get to product category name, I have to invoke
db.Categories and affect the result to any viewdata.
Can anybody explain to me how this is working?
My guess is that you're running into a side effect of Model Binding. Does the Products class have a property for the Category class?

Resources