I am creating a view page where I need to display data and as well as a form to insert data. To insert data I have bootstrap modal. How can I bind my view page so that I can have data to display in the page as well as create form to insert data. I mean how can I bind my view to display data?
public ActionResult GetFirm()
{
return View(db.FirmModels.ToList());
}
My view page
#model models.FirmModel
// code for bootstrap modal
// code for data table
<table id="tblFirmData">
<thead>
<tr>
<th>Edit/Print</th>
<th style="visibility:hidden;">#Html.DisplayNameFor(model => model.FirmId)</th>
<th>NAME</th>
<th>CONTACT</th>
</tr>
</thead>
<tbody>
#foreach(var item in models)
{
int status = item.FirmRegistrationStatus;
}
</tbody>
</table>
When I do foreach(var item in models) getting error 'models' is a namespace but is used like a variable and when I do #foreach(var item in Model) I am getting error foreach statement cannot operate on variables of type 'FirmModel' because 'FirmModel' does not contain a public instance definition for 'GetEnumerator'.
How to solve this problem, shall I need to modify my GetFirm return method or need to change in view page?
Because of you pass a list to the view define you view model as:
#model IEnumerable<models.FirmModel>
The IEnumerable interface is implementing the GetEnumerator() method used to iterate through the collection.
Or:
#model IList<models.FirmModel>
The IList interface inherits the IEnumerable.
And correspondingly:
#foreach(var item in Model)
{
....
}
I am using SimpleFormController with a result page looking like this:
<tr>
<td>Name: </td>
<td>${product.name}</td>
</tr>
<tr>
<td>Text: </td>
<td>${product.text}</td>
</tr>
A user can enter a name and some text. I'm trying to implement a delete functionality for each entry (there should be a link next to each entry). I'm having trouble with understanding, if it can be done in the same Controller as for the input or not (am new to Spring) and how. The onSubmit method helps to display data that was added, do I need to implement an extra delete method? If yes, how can I "map" it to my delete link in my jsp?
I suppose you are not wanting to put a delete link even when the user is just entering the name!
Delete links should normally appear when you are displaying data, not creating them.
Here is how you can create a delete link according to associated ids.
<tr>
<td>Name: </td>
<td>${product.name}</td>
<td>delete</td>
</tr>
and this should be in your controller:
#Controller
public class ProductController{
#RequestMapping("/delete/{id}")
public String deleteProduct(#PathVariable("id")Integer id) {
// get product by id
// delete that product
// save database
// or do as you wish
return "redirect:/index";
}
}
Hope that helps :)
I am generally new to ASP.NET and am modifying some code that I've inherited. There is a section of code that creates a Select box using a ListBoxFor based on a search term that's entered by the user:
#Html.ListBoxFor(m => m.SelectedItem,
Lookup.Models.myService.Search(Model.SearchTerm,
null == Model.SelectedCity ? 1 :
Int32.Parse(Model.SelectedCity))
The signature for Search() is:
public static List<SelectListItem> Search(string term, string city)
Instead of displaying a Select box, I want to output an HTML table instead with the data. I'm not even sure how to go about doing this or really what info to give you all in order to help me :)
The ListBoxFor helper displays <select> elements with multiple="multiple" attribute allowing multiple selections. If you want something else you should not use this helper. So you said that you wanted an HTML table.
Now, there's something very wrong with the code you have shown. You are calling Lookup.Models.myService.Search inside a view. Views are not supposed to pull data from some places. They are supposed to only display data that is being passed to them under the form of view models by a controller action. So this call should not be done in the view. It should be done beforehand and the result stored as a property on your view model:
public IEnumerable<SelectListItem> Items { get; set; }
Anyway. The first possibility is to write the markup yourself:
<table>
<thead>
<tr>
<th>Value</th>
<th>Text</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Items)
{
<tr>
<td>#item.Value</td>
<td>#item.Text</td>
</tr>
}
</tbody>
</table>
Of course writing this code over and over again could become cumbersome. So you could externalize it in a DisplayTemplate. For example you could put it inside a ~/Views/Shared/DisplayTemplates/MyTableTemplate.cshtml and then when you needed to render it in a view you could use:
#Html.DisplayFor(x => x.Items, "MyTableTemplate")
I want to be able to update a model and all its collections of child objects in the same view. I have been referred to these examples: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx and http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/ .
For example, I have an object Consultant, that has a collection of "WorkExperiences". All this is in an Entity Framework model. In the view, the simple properties of the Consultant object is no problem, but the collection I cannot get a textbox to show up for. I tried following the examples in the links above, but it doesn't work. The problem is, in those examples the model is just a list (not an object with a child list property). And also, the model again is an EF model. And for some reason that doesn't seem to work as in those examples.
Just to make it simple, I tried to do something along the lines of Phil Haacks example, and just get the View to show the textbox:
#for (int i = 0; i < Model.WorkExperiences.Count; i++)
{
Html.TextBoxFor(m => m.WorkExperiences[i].Name);
}
I tried to create a new WorkExperience object in the controller for the ViewModel:
public ActionResult Create(int id)
{
Consultant consultant = _repository.GetConsultant(id);
DetailsViewModel vm = new DetailsViewModel();
vm.WorkExperiences = consultant.WorkExperiences.ToList();
vm.WorkExperiences.Add(new WorkExperience());
return View(vm);
}
But the View doesn't show any empty textbox for the WorkExperience Name property. If on the other hand I create a separate View just for adding a new WorkExperience object, passing a new empty WorkExperience object as the model, this works fine:
#Html.EditorFor(model => model.Name)
That gives me an empty textbox, and I can save the new object. But why can't I do this in the same view as the Consultant object, with collections according to the examples in the links above?
BTW, this is sort of a follow-up question to an earlier one, that pointed me to the above links, but I never got to a final solution for it. See that question if more info is needed: Create Views for object properties in model in MVC 3 application?
UPDATE:
According to answers and comments below, here's an update with the View and an EditorTemplate:
The View:
#model Consultants.ViewModels.DetailsViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Add work experience", "CreateWorkExperience", new { id = ViewBag.Consultant.Id })
</p>
<table>
<tr>
<th></th>
<th>
Name
</th>
</tr>
#foreach (var item in Model.WorkExperiences) {
<tr>
<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>
<td>
#item.Name
</td>
</tr>
}
</table>
#for (int i = 0; i < Model. WorkExperiences.Count; i++)
{
Html.EditorFor(m => m. WorkExperiences[i]);
}
(Please note that all this is not really how I'll design it in the end, all I am after right now is to get the WorkExperience object to show up as an empty textbox to fill out, and to be able to add and delete such textboxes as in Phil Haack's and Steven Sanderson's examples.)
The EditorTemplate:
#model Consultants.Models.WorkExperience
#Html.TextBoxFor(m => m.Name);
This stuff with the EditorTemplate works fine in Phil Haack's sample project, which I downloaded to try, but here, with the EF model or whatever the problem is, I don't get any textbox at all. The table in the view is just there as a test, because in the table I do get the rows for WorkExperiences, whether I add an empty WorkExperience object or fill out its properties doesn't matter, the rows show up for each object. But again, no textbox...
For example, I have an object Consultant, that has a collection of "WorkExperiences". All this is in an Entity Framework model.
That's the first thing you should improve: introduce view models and don't use your domain models into the view.
This being said let's move on to the templates. So you can completely eliminate the need to write loops in your views.
So here's how your view might look like:
#model Consultants.ViewModels.DetailsViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Add work experience", "CreateWorkExperience", new { id = ViewBag.Consultant.Id })
</p>
<table>
<tr>
<th></th>
<th>
Name
</th>
</tr>
#Html.DisplayFor(x => x.WorkExperiences)
</table>
#Html.EditorFor(x.WorkExperiences)
So as you can we are using a display template and an editor template. Let's define them now.
Display template (~/Views/Shared/DisplayTemplates/WorkExperience.cshtml):
#model AppName.Models.WorkExperience
<tr>
<td>
#Html.ActionLink("Edit", "Edit", new { id = Model.Id }) |
#Html.ActionLink("Details", "Details", new { id = Model.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = Model.Id })
</td>
<td>
#Model.Name
</td>
</tr>
Editor template (~/Views/Shared/EditorTemplates/WorkExperience.cshtml):
#model AppName.Models.WorkExperience
#Html.TextBoxFor(x => x.SomePropertyOfTheWorkExperienceModelYouWantToEdit)
...
What is important here is the naming convention. The name of the template should be the name of the type of the item in the collection. So for example if in your view model you have a property
public IEnumerable<Foo> { get; set; }
the corresponding template should be called Foo.cshtml and should be located in ~/Views/Shared/DisplayTemplates or ~/Views/Shared/EditorTemplates depending on its role.
So as you can see we have gotten rid of the nasty loops. Now not only that the views look clean, but you get correct names for the input fields so that you can bind the values back in the post action.
The easiest way to do this is probably to create a WorkExperienceList class that inherits List<WorkExperience> (or List<string>, if that's what they are) and then create a custom template for your WorkExperienceList. That way, you'd simplify your view code to #Html.EditorFor(Model), and ASP.NET MVC would take care of the rest for you.
I'm trying to do an Ajax delete in a fairly standard Index view, i.e. I have a generated Index view with one added filter drop-down, of little relevance here. I have changed the free Delete Html.ActionLink on every row to an Ajax.ActionLink, and the delete and ajax update work, but whichever container div I try and update, I always somehow get some kind of nesting in the updated page, e.g. after a delete and update, I get duplicate Home and About links from the master page inside my content.
Here is my current action link that causes what I describe above:
<%: Ajax.ActionLink("Delete", "Delete", new { id = item.InstallationDBNumber }, new AjaxOptions { UpdateTargetId = "jobList" }) %>
... and here is where jobList is located, just outside the table used for the index list:
<div style="clear: both;">
</div>
<div id="jobList" class="index-list">
<table>
<tr>
You should post your code for your Delete action method on your controller. But from the sounds of it, you are returning Return View(myModel) instead of Return PartialView("partialViewName", myModel).
Create a partial view contianing the layout information for jobList and return that from your controller action method.