I have a Razor view rendering a nested collection which includes the following code...
<td>
#Html.TextBoxFor(x => x.Fitments[i].AncillaryProducts[ai].Description)
#Model.Fitments[i].AncillaryProducts[ai].Description
</td>
This should display an edit box followed by the text of the edit boxes value, but the resulting html is...
<td>
<input name="Fitments[0].AncillaryProducts[0].Description" class="valid" id="Fitments_0__AncillaryProducts_0__Description" aria-invalid="false" type="text" value="Valve (alloy/mobile)">
Valve (alloy/center)
</td>
Where the text boxes value "Valve (alloy/mobile)" is clearly different to the actual value "Valve (alloy/center)". How is this even possible?
The view is posted to the action method where AncillaryProducts is cleared...
foreach (var fitment in model.Fitments)
fitment.AncillaryProducts.Clear();
Then (different) ancillary products are added...
fitment.AncillaryProducts.Add(new JobCardAncillaryProduct() { Description = p.Description });
TextBoxFor is rendering the previous value of that array entry and Razor is rendering the current value.
Any help much appreciated.
Related
I have the following code in my view:
<table>
<tr>
<td>
Number of Records to Show:
</td>
<td>
#Html.DropDownListFor(m=>m.NumRecsToShow, Enumerable.Range(1, 100).Select(i => new SelectListItem {Text = i.ToString(), Value = i.ToString()}))
</td>
</tr>
<tr>
#Html.PagedListPager((IPagedList) Model.lp, page => Url.Action("List", new RouteValueDictionary()
{
{"Page",page},
{"Recs",?????}
}))
</tr>
</table>
What I need to do is read the new selected value and pass it back as a "Recs" parameter, so I can return the right number of Records. But I dont know how to read the selected value when the PagedListPager number is clicked on in the table. I would love to know of some #Html helper (Where the ???? is in the code above.) that can read the value when I need it, but I am starting to think that I might need to use JQuery. Of course the other route would be if I can use the DropdownList to change the model data then I can just pass back the model to the controller, but the dropdownlist doesnt seem to get read unless I do a form submit.
Any pointing me in the right direction is appreciated.
I have an MVC5/Bootstrap application that has a page where the user, as part of a larger form, can add and delete rows in a table.
To add rows, the user clicks an icon and then searches for data using a TypeAhead field that appears in a popover, which when selected retrieves row data using AJAX and inserts the row into the table.
Rows can be deleted by clicking on an icon in each row, the row is then removed. Both these actions affect a bound hidden input field that contains a list of IDs of the rows, e.g. "{100001},{100003},{100004}".
When the form that contains this table is submitted this hidden field is parsed and the appropriate database actions are performed using EF6 to add or delete items.
My question is whether this approach of using a single hidden field that is manually parsed by the controller method is the best choice. I was thinking there may be a more idiomatic way to utilize MVC model binding. e.g. having hidden checkboxes on each row or some such mechanism.
The ViewModel you are binding to could contain a collection of row viewmodels that wrap all inputs for a single row.
To submit these, bind them using the index.
<table>
<tbody>
<tr>
<td>
#Html.HiddenFor(m => m.RowData[0].SomeRowProperty)
<input type="hidden" name="RowData.Index" value="0" />
</td>
</tr>
<tr>
<td>
#Html.HiddenFor(m => m.RowData[1].SomeRowProperty)
<input type="hidden" name="RowData.Index" value="1" />
</td>
</tr>
</tbody>
</table>
See also Model binding to a list
I want to create simple list in a form of table like on the image:
I am confused how to implement update/delete actions.
Both are [HttpPost] methods.
But I can't create forms inside <td> tags.
What is the valid way to make a table in the way that I want?
I think I have understood what do you need.
You can make one simple table and into each row put only one td which keep form.
Something like this:
<table>
#{
foreach (var item in Model.MyCollection)
{
<tr>
<td>
<form>
<table>
and hear put your existing row with your columns <tr><td>...</td><td>...</td></tr>
</table>
</form>
</td>
</tr>
}
}
and you will have one form for each record.
I'll use the famous NerdDinner as an example here.
I have a search page where the user can enter a search string and then see the result in a table below. The user can also add more results to the table, like this:
Search for dinners today and display in a table.
Search for dinners tomorrow and add the result to the table.
The table will now show dinners today and tomorrow.
The user is also able to remove dinners from the table by clicking on them, one by one.
I need to generate a pdf with the results in the table. Not like a print screen because the pdf has it's own layout. I just need the data in the table. Preferably in a list of Dinner models.
Right now I can generate a pdf from a list of Dinner models. But once I've printed them to the table and the user has manipulated it I don't know how to get it back to a list of Dinner models.
Another solution could be to keep the Id's hidden in the table and then do another search in the DB with the Id's from the table (after the user has manipulated it). At least then I would get the result in the form of a list of Dinners. But this seems redundant to me.
Has anyone had a similar problem and how did you solve it?
You could put the table inside an html <form> and on each row in addition to the label you could have a hidden field:
#model IEnumerable<Dinner>
#using (Html.BeginForm())
{
<table>
<thead>
<tr>
<th>Prop1</th>
<th>Prop2</th>
<th>Prop3</th>
</tr>
</thead>
<tbody>
#Html.EditorForModel()
</tbody>
</table>
<input type="submit" value="Export to PDF" />
}
and in the editor template:
#model Dinner
<tr>
<td>
#Html.DisplayFor(x => x.Prop1)
#Html.HiddenFor(x => x.Prop1)
</td>
<td>
#Html.DisplayFor(x => x.Prop2)
#Html.HiddenFor(x => x.Prop2)
</td>
<td>
#Html.DisplayFor(x => x.Prop3)
#Html.HiddenFor(x => x.Prop3)
</td>
</tr>
Now this form could be submitted to the following controller action:
public ActionResult GeneratePdf(IEnumerable<Dinner> dinners)
{
byte[] pdf = ...
return File(pdf, "application/pdf", "dinners.pdf");
}
You may also checkout the following blog post for managing a variable length list in order to keep input field names in sync for the binder when adding/removing elements.
Suppose I have a simple search form with a textbox. And upon submitting the form I send the contents of the textbox to a stored procedure which returns to me the results. I want the results to be displayed on the same page the form was, except just below it.
Right now I'm doing the following but it's not working out exactly the way I want:
"Index" View of my SearchController
#using (Html.BeginForm("SearchResults", "Search", FormMethod.Post, new { #class = "searchform" }))`{
<fieldset>
<legend>Name</legend>
<div class="editor-label">
#Html.Label("Search")
</div>
<div class="editor-field">
#Html.TextBox("Name")
</div>
<input type="submit" value="Search" class="formbutton" />
</fieldset>
#{ Html.RenderPartial("SearchResults", null);
This is my "SearchResults" View:
#model IEnumerable<MyProject.Models.spSearchName_Result>
<table>
#foreach (var item in Model)
{
<tr>
<td>
#item.Name
</td>
</tr>
}
</table>
This is my Controller:
// GET: /Search/SearchResult
[HttpPost]
public ActionResult SearchResult(FormCollection collection)
{
var result = myentity.spSearchName(collection["Name"]);
return PartialView("SearchResults", result);
}
I can only seem to get the results to display on an entirely new page (not being embedded as a partial view), or I get an error when I load the search page because there are no results (since I hadn't searched yet).
Is there any better way to achieve what I'm trying to do? I feel like I'm going against some of the best practices in MVC.
You could return the results in a ViewData object then only show on the view it if is not null.
Very similar to this question MVC 3 form post and persisting model data
For this instance it looks like you are not passing the results to your partial view. Try this?
#{ Html.RenderPartial("SearchResults", Model.Results);
Since you are not persisting your search information using a model, the search information will be lost when the search form is posted.
Given your design and stated goal, it would be best to convert the form in your Index view into an Ajax form, then your controller can send your partial view back to populate a div below your Ajax form.
counsellorben