Search code examples
c#asp.net-mvcrazorasp.net-mvc-5mvc-editor-templates

EditorTemplate not rendering as expected?


I have a requirement to be able to dynamically add/remove rows to a Tabel in an MVC 5 Application I am working on. I have also included knockout in my project as I use it to post back to preform calculation on my viewModel.

What I have done so far is created a List on my User Model to hold the details of the AdditionalUsers:

public List<AdditionalUser> AdditionalUsers { get; set; }

Additional User class defined as:

public class AdditionalUser
{
    public string FirstName { get; set; }
    public string Surname { get; set; }
    public double Cost { get; set; }
}

I then created a EditorTemplates folder and created a partial view _AdditionalUser.cshtml as below:

@model MyProject.Models.AdditionalUser

<td>
    @Html.TextBoxFor(model => model.FirstName)
</td>
<td>
    @Html.TextBoxFor(model => model.Surname)
</td>
<td>
    @Html.TextBoxFor(model => model.Cost)
</td>

Where I need this rendered on my User View I have done the following:

        <tr>
            @Html.EditorFor(model => model.AdditionalUsers)
        </tr>

Each other on the view has 3 . Doing this then in my controller where I new my User model I did:

model.AdditionalUsers =  new List<AdditionalUser>(2);

I would have thought that would have created two blank rows in the tr where I called EditorFor but nothing is rendered? This was just for my first test to get the EditorTemplate working. I want to then wire this up to knockout to Add and remove the rows dynamically but first I am wondering why the EditorTemplate is not rendering as expected?


Solution

  • Your editor template is named incorrectly. There are two ways for MVC to pick it up:

    By Name

    Name the template with the exact same name as the data type:

    DateTime.cshtml
    String.cshtml
    AdditionalUser.cshtml
    

    Explicitly

    In the property of your model, use the UIHint attribute:

    public class MyModel
    {
        public SomeObject TheObject { get; set; }
    
        [UIHint("SomeObject")]
        public SomeObject AnotherObject { get; set; }
    
    }
    

    Additionally your code is not quite correct to get the rows rendered. You should first add the tr tag to the view:

    @model MyProject.Models.AdditionalUser
    
    <tr>
        <td>
            @Html.TextBoxFor(model => model.FirstName)
        </td>
        <td>
            @Html.TextBoxFor(model => model.Surname)
        </td>
        <td>
            @Html.TextBoxFor(model => model.Cost)
        </td>
    </tr>
    

    Next change your parent view to something like this (note I've added table header row for clarity):

    <table>
        <tr>
            <th>@Html.DisplayNameFor(m => m.FirstName)</th>
            <th>@Html.DisplayNameFor(m => m.Surname)</th>
            <th>@Html.DisplayNameFor(m => m.Cost)</th>
        </tr>
        @Html.EditorFor(model => model.AdditionalUsers)
    </table>