Ctrl_Alt_Defeat
Ctrl_Alt_Defeat

Reputation: 4009

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?

Upvotes: 3

Views: 1345

Answers (4)

DavidG
DavidG

Reputation: 118947

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>

Upvotes: 1

adhie
adhie

Reputation: 284

You can drop the "_" character from the name, or there is an overload, that takes a template name as the second argument.

@Html.EditorFor(model => model.AdditionalUsers, "_AdditionalUsers")

Upvotes: 1

Onur Topal
Onur Topal

Reputation: 3061

here is the rules

1- the name of the template must be same. in your case it must be AdditionalUser.cshtml 2- MVC first looks if a folder EditorTemplates exists in the parent folder of the view (which has controller name) then looks at Shared folder.

But in your case @Html.EditorFor(model => model.AdditionalUsers) is would not work as the type is List and as far as I know there is no way to do that so use a foreach loop;

@foreach (var u in model.AdditionalUsers) {
    @Html.EditorFor(model => u)
}

should do the trick.

Upvotes: 0

Shyju
Shyju

Reputation: 218732

In your GET action method, you need to return some item in the AdditionalUsers collection. Try this.

var yourViewModel=new YourViewModel();

var userList =  new List<AdditionalUser>();
userList.Add(new AdditionalUser { FirstName ="A"} );
userList.Add(new AdditionalUser{ FirstName ="B"});

yourViewModel.AdditionalUsers =userList();
return view(yourViewModel);

Also your editor template name should be same as the class name which is strongly typed to the editor template razor view, which is AdditionalUser.cshtml

Upvotes: 0

Related Questions