Replacing a <tr> using ASP.MVC Ajax - asp.net-mvc

I have the following ajax form tag:
When the form is submitted, the controller returns a partial with a full row to be inserted into the table (the same partial is also used to render the table in the first place).
The idea is that after the user edits an item, the item's row in the table will be replaced with the updated version from the partial. When I point UpdateTargetId to a <div> element it seems to work fine, but when I point it to a <tr> element, it doesn't.
Any help would be greatly appreciated.

I'm assuming that your partial actually renders the entire row. In that case, the default replacement semantics won't work for the <tr> element since you'll be inserting a new row into the existing row and get something like:
<tr><tr>...new contents</tr></tr>
You might want to look at changing the InsertionMode (I forget the other potential options) or having your partial generate just the row contents, i.e., the <td> elements instead of the row itself.

I ended up changing my approach. I changed the controller to return the values of the object in jason and had the view's js function simply update the content of the table row with the new values. Seems to work fine now.

Rich Strahl has an excellent post on how to do Client Templating with jQuery.

Related

How do I get my WebGrid to POST instead of GET during a sort or paging operation in my MVC4 site?

I have a fairly simple site with a Search partial view and a Listing partial view. They're rolled up using multiple models into the Index view.
Everything is fine. Except when I click the grid column headers to sort or attempt to page to the next listing of data, the grid comes back empty. If I re-submit the same search criteria, then the grid repopulates with all applicable data sorted or paged properly.
I've tracked this behavior down to the fact that the WebGrid sets up it's paging and sorting mechanisms as a GET instead of a POST. So obviously all my model data is left off the submission.
Isn't there a way to get the WebGrid to POST so the data tags along? Seems quite counterproductive for the WebGrid as a class to not include the data one wants to page or sort.
Old question, but just to add a reference:
I preferred the solution suggested at this link
which solves the problem using JQuery:
var links = $('a[href*=page], a[href*=sort]'), form = $('form');
links.click(function () {
form.attr("action", this.href);
$(this).attr("href","javascript:");
form.submit();
});
This may not be the most elegant solution, but it works:
Add the model to your Session in the view:
Session.Add( "Model", Model );
Then, in the Index GET Action in your controller (or whatever the GET Action is), just check for the value and call the POST Action:
if ( Session[ "Model" ] != null )
this.Index( Session[ "Model" ] as MyModel );
Cleanup your Session accordingly.
Further to the JQuery answer above (which brought me success, thanks!) don't forget to undelegate the the webgrid's own magic methods that it adds behind the scenes. Otherwise you may end up with another ajax GET occurring at the same time as your POST.
Before binding to the 'page' and 'sort' links do this:-
$("#MyWebGridID").undelegate();

Build table using partial view with Ajax requests

I need to dynamically create (insert) a new table row every time user presses button (using Ajax). My partial view structure:
<tr>
<td><td>
<td><td>
...
</tr>
When I need insert new row at the end I can do something like this:
element_table.innerHTML += ajax_data
But what I must do when I need to place it between other rows?
I can return only [td] elements and wrap them in [tr] clientside created element (tr.innerHTML = ajax_data) but I don't think this is a good idea.
Any ideas?
Are there any common practises?
The easiest way is to use jQuery with your Ajax response. It can be as simple as
$('#table').append(response)
to append a row. It's also possible to insert the new row at a specific index:
$('#my_table > tbody > tr').eq(index).after(response);
Note that index is 0 based.

MVC3 ModelBinding to a collection posted back with index gaps

I have a collection of objects on my Model that I'm rendering in a View by using EditFor function, and I have an EditorTemplate which is responsible for actually rendering each object.
#Html.EditorFor(model => model.MyObjects)
This has worked well for a while now, and when you check the html, my text boxes are prefixed with the model property, followed by the index of the collection they came from.
<input class="text-box single-line" id="MyObjects_2__SomeProperty"
name="MyObjects[2].SomeProperty" type="Text" value="" />
However I've recently started using the ShowForEdit and ShowForDisplay properties in the model metadata for the collection, and in the first line of my editor template if the ShowForEdit is not true, I just skip it.
#if (!ViewData.ModelMetadata.ShowForEdit)
{
return;
}
But because these are all indexed in the html, when I try to save this collection back to the viewmodel via a postback, it fails because of a reliance on the indexing numbers. Every item in the collection after the missing index is missing from my view model when I check it's value.
In this case it's actually my first item in the collection that I'm skipping since I don't want it to be visible on the edit view, but because of this when I postback the first index in the html is 1 (instead of 0 like it normally would be), but this is a problem when you try to save the changes. This is also a problem when altering the DOM using javascript.
Has anyone else encountered a problem with the default model binder's ability to read data posted back when one or more indexes in the html represented collection are not present?
Are there model binders that handle this problem?
Ran into this issue recently and solved it by converting the List to a Dictionary<string, model> with GUIDs as the key.
#foreach (var index in Model.EmailAddresses.Keys)
{
<label asp-for="#Model.EmailAddresses[index].Email">Email</label>
<input asp-for="#Model.EmailAddresses[index].Email" type="text" />
}
This avoided having to include hidden inputs that map to the index value.
There are some very good blog posts that allow you to modelbind to a list without the need to provide zero based contiguous index. plz have a look at
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
http://zahidadeel.blogspot.com/2011/05/master-detail-form-in-aspnet-mvc-3-ii.html
Furthermore, if you are interested in MVVM pattern and knockout js you can check this great work by steve sanderson
For more reading put "editing varibale length list mvc style" in google and it will give u a dozen useful links

asp.net mvc: What is the correct way to return html from controller to refresh select list?

I am new to ASP.NET MVC, particularly ajax operations. I have a form with a jquery dialog for adding items to a drop-down list. This posts to the controller action.
If nothing (ie void method) is returned from the Controller Action the page returns having updated the database, but obviously there no chnage to the form. What would be the best practice in updating the drop down list with the added id/value and selecting the item.
I think my options are:
1) Construct and return the html manually that makes up the new <select> tag
[this would be easy enough and work, but seems like I am missing something]
2) Use some kind of "helper" to construct the new html
[This seems to make sense]
3) Only return the id/value and add this to the list and select the item
[This seems like an overkill considering the item needs to be placed in the correct order etc]
4) Use some kind of Partial View
[Does this mean creating additional forms within ascx controls? not sure how this would effect submitting the main form its on? Also unless this is reusable by passing in parameters(not sure how thats done) maybe 2 is the option?]
UPDATE:
Having looked around a bit, it seems that generating html withing the controller is not a good idea. I have seen other posts that render partialviews to strings which I guess is what I need and separates concerns (since the html bits are in the ascx). Any comments on whether that is good practice.
look at the ContentResult you can specify the mime type of what you return (text/html)
You could alternatively make a control that take a IEnumerable of whatever you put in the selectlist, and build it using the view engine. That way you keep the formatting of the html (in this case a list of options) into a view, and not in your code.
<%# Control Language="C#"Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Article>>"%>
<%foreach (var article in Model){%>
<option><%:article.Title %></option>
<%} %>
I think I would go for that second one
From what I understood, the jQuery dialog contains a form that, when submitted, will post to an action which updates the database with some information. You want to get the newly added database information and update the same form that was used to trigger the database update.
If that is the case, then I think the best clean and logical option is to return JSON serialization of the items to be put in the drop down right after you update the database. Then, using jQuery, you would clear the drop down and append option tags into it.
You can also write a new, seperate action that returns the JSON serialization of the database objects you need. You would have jQuery call another post to this action as a callback to your first ajax post (the one used to update the database).
Here is a quick snippet
public ActionResult UpdateDatabase(string something)
{
/// update the database
IEnumerable<Items> items = getItemsFromDatabase(); // or w/e
var vals = items.Select(x=> new { value = x.ID, text = x.Name }); // something similar
return Json(vals);
}
Personally, I would write a separate function that returns JSON. This ensure separation of concerns, and gives me a function I can use in many different places.
Returning a JsonResult with all the items is the most versatile and least-bandwidth intensive solution as long as you are happy to iterate through the list in jQuery and update your drop-down list.
Using a partial view is nice for HTML that you can .load(...) directly into your select, but less versatile.
I would go with the JsonResult.
In your Controller:
public JsonResult UpdateItem(string sItem)
{
// 1. Insert new item into database if not exist...
// {update code here}
// 2. retrieve items from database:
IEnumerable<Item> Items = GetItems();
// 3. return enumerable list in JSON format:
return new JsonResult{ Data = new {Items = Items, Result = "OK" }};
}
On client-side:
Iterate through Items array and add the items to your list.

MVC Index page and filter

This seems like a very simple question, but I'm getting lost, and need a few pointers.
I am using ASP.NET MVC C#, and have an Index page which displays a list of items, which is working fine.
Now I'm trying to add a DropDownList that depending on what the user selects will filter the list of items. But I keep thinking how you would do this in ASP.NET Web with RunAt Server, which I know is wrong.
Any pointers would be welcomed.
Put the select box in a form and make the form post back to a filter method in your controller.
Or
If you want to use ajax, use an Ajax.ActionLink to update the table with the filtered results
<% Ajax.ActionLink("Filter", "FilterMethod", null, new AjaxOptions { UpdateTargetId = "tableId" }, new { Title = "Filter results" }) %>
<table id="tableId"> .... </table>
Where "FilterMethod" is in yo0ur controller
This might help.
Also worth looking at:
http://jerrytech.blogspot.com/2009/06/implement-ajax-form-in-mvc-framework.html

Resources