开发者

Generate distinct client ids in ASP.NET MVC3 when repeating over list of items

I have an ASP.NET MVC3 Razor view that renders editors for a list of customers inside a jQuery UI accordion. At the moment all client-side id's for similar customer properties are the same in the rendered html. For obvious reasons I'd like to change this.

My main view is as follows:

<div id="accordionKlanten">
@foreach (var customer in Model.Customers)
{
    <h3><a href="#">@customer.Name</a></h3>
    <div>@{ Html.RenderPartial("CustomerData", customer); }</div>
}
</div>

And in my CustomerData view (greatly simplified):

@using (Ajax.BeginForm("UpdateCustomer", ajaxOptions))
{
    @Html.LabelFor(model => model.Name)
    @Html.TextBoxFor(model => model.Name)
    <input type="submit" value="Opslaan" />
}

This all works perfectly: I can post to my UpdateCustomer action method, the model object is bound and a partial view is returned that is rendered back to the client.

But when I have three customers this renders three input fields in my html with id="Name". One of the things that goes wrong is that the <label for="Name">...</label> doesn't work since Name is not a unique id.

Is there any way to tell tell ASP.NET MVC3 to render distinct id's (while leaving the name attributes intact, as these are used to bind to the model)?

For the sake of completeness, here are the two action methods involved:

// Returns view that renders editor for each customer.
public ActionResult Index()
{
    var customers = _customerService.GetCustomers();
    return View(new CustomersViewModel { Customers = customers });
}

// Updates a customer and returns a partial view.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateCustomer(CustomerDto customer)
{
    // Update customer in database.
开发者_开发知识库    return PartialView("CustomerData", customer);
}


Instead of writing ugly loops in a view:

<div id="accordionKlanten">
@foreach (var customer in Model.Customers)
{
    <h3><a href="#">@customer.Name</a></h3>
    <div>@{ Html.RenderPartial("CustomerData", customer); }</div>
}
</div>

use editor templates:

<div id="accordionKlanten">
    @Html.EditorFor(x => x.Customers)
</div>

and in the corresponding editor template (~/Views/Shared/EditorTemplates/Customer.cshtml):

@model Customer
<h3>
    <a href="#">@customer.Name</a>
</h3>
<div>
    @Html.EditorFor(x => x.FirstName)
</div>
<div>
    @Html.EditorFor(x => x.LastName)
</div>
...

Now the Customer editor template will be executed automatically for each element of the Customers collection property on your model. The only requirement is to respect the naming convention: it should be situated in the ~/Views/Shared/EditorTemplates folder and it should be named as the type of the collection item. So for example if the property is IEnumerable<CustomerViewModel>, the editor template should be named CustomerViewModel.cshtml and obviously be strongly typed to CustomerViewModel.

That's all. Now not only that you have cleaned your view but proper names will be used.


Use a for loop instead of a foreach loop in your main view.

@for (var i = 0; i < Model.Customers.Count; i++)
{
    <h3><a href="#">@customer.Name</a></h3>
    <div>@{ Html.RenderPartial("CustomerData", Model.Customers[i]); }</div>
}

You will have to adjust this to use a List<Customer> or an Customer[].

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜