Reputation: 1454
I need to allow customers to specify which fields will be drawn in which order, from among a fixed set of fields (address, home phone, SSN, first name, etc. etc.)
What is the best practice for this? I feel like an HTML helper method like "DrawField" is appropriate, but can I use helpers like Html.EditorFor in the body of an HTML helper method? When modelstate has errors and I redisplay the form, will the submitted values and errors be populated?
The "safest" approach seems to be an ugly big loop:
foreach( Field f in FieldList)
{
if(f.Key == FieldKey.FirstName)
{
@Html.LabelFor(model => model.FirstName, StringResource("firstNameLabel"))
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
<br />
}
if(f.Key == FieldKey.LastName)
{
......
}
}
There's gotta be a better way!
Upvotes: 1
Views: 527
Reputation: 32768
Although I haven't tried you can try by creating a custom editor / display templates for the Model that takes care of ordering the fields.
To get a basic idea about model templates check this link http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html
UPDATE:
I've tried a simple example. We have a Person
model and I want to control the order in which the FirstName
and LastName
are displayed.
public class Person
{
[Required(ErrorMessage = "The field is required")]
[Display(Name = "First Name:")]
public string FirstName { get; set; }
[Required(ErrorMessage = "The field is required")]
[Display(Name = "Last Name:")]
public string LastName { get; set; }
}
Create a custom editor template Person.cshtml
and place it in the Views/Shared
folder. So whenever you call the EditorFor
method for
Person
this template will be used for rendering. For simplicity I'm passing the order in which they have to displayed as an array of fields through ViewBag
.
@model RazorAndJson.Models.Person
@{
var fields = ViewBag.FieldsOrder != null
? ViewBag.FieldsOrder
: new[] { "FirstName", "LastName" };
}
@foreach(string field in fields)
{
<p>
@Html.Label(field)
@Html.Editor(field)
@Html.ValidationMessage(field)
</p>
}
Upvotes: 0
Reputation: 39268
Since the list of fields is fixed I would just order it in the controller and just have n regions in the view that will render the fields in the order they arrive in the model. I would structure the model so that it contains a list of the same object, but the content will be different for each one (First name, last name etc) .You can add whatever meta data you need to your model
@Html.LabelFor(model => model.Items[0].Prop, StringResource(model.Items[0].PropName))
@Html.EditorFor(model => model.Items[0].Prop)
......
That way you don't need any conditionals or loops. It's instead n generic regions driven by the data
Upvotes: 1