0

still now i generate html table like below code example but interested to know how could i generate html table using editorfor using editor template

see my full razor and view model code and guide me how to achieve my goal.

@model MVCCRUDPageList.Models.StudentListViewModel
@{
    ViewBag.Title = "Index";
}

<h2>CREATE TABULAR UI WITH HTML TABLE</h2>

@using (Html.BeginForm("Index", "HtmlTable", FormMethod.Post))
{
    <div class="form-group">
        <div class="col-md-12 table-responsive">
            <table class="table table-bordered table-hover">
                <tr>
                    <th>
                        Row No
                    </th>
                    <th>
                        ID
                    </th>
                    <th>
                        Name
                    </th>
                    <th>
                        Country
                    </th>
                    <th>
                        Hobbies
                    </th>
                    <th>
                        Sex
                    </th>
                </tr>
                }

                @for (int x=0; x<=Model.Students.Count-1;x++)
                {
                    <tr>
                        <td>
                            <label>@(x+1)</label>
                        </td>
                        <td>
                            @Html.TextBoxFor(m => m.Students[x].ID)
                        </td>
                        <td>
                            @Html.TextBoxFor(m => m.Students[x].Name)
                        </td>
                        <td>
                            @Html.DropDownListFor(m => m.Students[x].CountryID,
                              new SelectList(Model.Country, "ID", "Name",  Model.Students[x].CountryID),
                             "-- Select Countries--", new { id = "cboCountry", @class = "edit-mode" })
                        </td>
                        <td>
                            @for (var i = 0; i < Model.Students.FirstOrDefault().Hobbies.Count; i++)
                            {
                                <div class="checkbox">
                                    @Html.HiddenFor(m => m.Students[x].Hobbies[i].ID)
                                    @Html.HiddenFor(m => m.Students[x].Hobbies[i].Name)
                                    @Html.CheckBoxFor(m => m.Students[x].Hobbies[i].Checked)
                                    @Html.LabelFor(m => m.Students[x].Hobbies[i].Name, Model.Students[x].Hobbies[i].Name)
                                </div>
                            }

                        </td>
                        <td>
                            @for (var i = 0; i < Model.Sex.Count; i++)
                            {
                                <div class="checkbox">
                                    @Html.HiddenFor(m => Model.Sex[i].ID)
                                    @Html.HiddenFor(m => Model.Sex[i].SexName)
                                    @Html.RadioButtonFor(m => m.Students[x].SexID, Model.Sex[i].ID)
                                    @Html.LabelFor(m => m.Students[x].SexID, Model.Sex[i].SexName)
                                </div>
                            }
                        </td>
                    </tr>
                }
            </table>
        </div>

        <input type="submit" value="Submit" />
    </div>
}

View Model Code

public class StudentListViewModel
{
    public IList<Student> Students { get; set; }
    public List<Country> Country { get; set; }
    public List<Sex> Sex { get; set; }


    public StudentListViewModel()
    {
        Students = new List<Student>
        {
            new Student
            {
                ID=1,Name="Keith",CountryID=0,SexID="F",
                Hobbies= new List<Hobby>
                {
                    new Hobby{ID=1,Name="Football",Checked=false},
                    new Hobby{ID=2,Name="Hocky",Checked=false},
                    new Hobby{ID=3,Name="Cricket",Checked=false}
                }

            },

            new Student
            {
                ID=2,Name="Paul",CountryID=2,
                Hobbies= new List<Hobby>
                {
                    new Hobby{ID=1,Name="Football",Checked=false},
                    new Hobby{ID=2,Name="Hocky",Checked=false},
                    new Hobby{ID=3,Name="Cricket",Checked=false}
                }
            },

            new Student
            {
                ID=3,Name="Sam",CountryID=3,
                Hobbies= new List<Hobby>
                {
                    new Hobby{ID=1,Name="Football",Checked=false},
                    new Hobby{ID=2,Name="Hocky",Checked=false},
                    new Hobby{ID=3,Name="Cricket",Checked=false}
                }
            }
        };

        Country = new List<Country>
        {
            new Country{ID=1,Name="India"},
            new Country{ID=2,Name="UK"},
            new Country{ID=3,Name="USA"}
        };

        Sex = new List<Sex>
        {
            new Sex{ID="M",SexName="Male"},
            new Sex{ID="F",SexName="Female"}
        };

    }
}

please guide me how to restructure my razor code to use editorfor and editor template for clean code. what will be name of editor template ?

thanks

Monojit Sarkar
  • 2,353
  • 8
  • 43
  • 94

1 Answers1

3

To use an EditorTemplate using @Html.EditorFor(m => m.SomeProperty) (where SomeProperty is a complex object, or collection of complex objects), then the template must be located in the /Views/Shared/EditorTemplates or /Views/YourControllerName/EditorTempates folder, and be named the same as the class name for SomeProperty.

In your case, if you want an EditorTemplate for typeof Student, then the template (a partial view) will be named Student.cshtml.

@model yourAssembly.Student
<tr>
    <td>@Html.TextBoxFor(m => m.ID)</td>
    <td>@Html.TextBoxFor(m => m.Name)<td>
    ....
<tr>

and in the main view, your would use

<table>
    <thead> .... </thead>
    <tbody>
        @Html.EditorFor(m => m.Students)
    </tbody>
</table>

which will generate the correct html for each item in your collection.

However, since you also have a dropdownlist for CountryID, then you need to pass the SelectList to the template (the template has no knowledge of the parent model) using additionalViewData, so the code needs to be modified to

@Html.EditorFor(m => m.Students, new { Countries = Model.Countries})

where the Countries property in StudentListViewModel should be

public IEnumerable<SelectListItem> Countries { get; set; }

and delete you current List<Country> Country property. Then in the view generate the dropdownlist using

<td>@Html.DropDownListFor(m => m.CountryID, (IEnumerable<SelectListItem>)ViewData["Countries "], "-- Select Country--", new { ... })<td>

Note you should not be adding new { id = "cboCountry" } because its creating invalid html (duplicate id attribute).

Now you can extend this further by creating an EditorTemplate for Hobby (which will be named Hobby.cshtml

@model yourAssembly.Hobby
<div class="checkbox">
    @Html.HiddenFor(m => m.ID)
    @Html.HiddenFor(m => m.Name)
    @Html.CheckBoxFor(m => m.Checked)
    @Html.LabelFor(m => m.Checked, Model.Name)
</div>

Note the LabelFor() should be for the Checked property, not the Name property as you currently have it.

Then in your Student.cshtml template, use

<td>@Html.EditorFor(m => m.Hobbies)<td>

to generate the correct html for each Hobby.

  • why you pass like `@Html.EditorFor(m => m.Students)` m.Students represent single student but we need to pass like `@Html.EditorFor(m => m.Students[i])` am i right or wrong ? – Monojit Sarkar Feb 22 '18 at 13:59
  • see this line please `@Html.EditorFor(m => m.Students, new { Countries = Model.Countries})` why i need to pass countries to child view because in my controller i have populated my countries in viewbag like `ViewBag.Countries = osvm._Countries;` so do not understand why i need pass again countries to child view student.cshtml? – Monojit Sarkar Feb 22 '18 at 14:04
  • i am not getting intellisense popup in Student.cshtml file inside EditorTemplates folder. is it normal or i made some mistake for which i am not getting intellisense popup? – Monojit Sarkar Feb 22 '18 at 14:07
  • you said "Note the LabelFor() should be for the Checked property, not the Name property as you currently have it." yes it is true and it is working and not throwing any error. so if i change from name to checked then what will be output? why you are saying it should be checked not name property ? – Monojit Sarkar Feb 22 '18 at 14:09
  • Sir i have placed a new post with code example which i tried but did not work. here it is https://stackoverflow.com/questions/48930025/asp-net-mvc-facing-difficulties-to-work-with-editortemplates please review my code and tell me where i made the mistake for which i am getting error for country dropdown and sex radio buttons. thanks – Monojit Sarkar Feb 22 '18 at 14:35
  • The answer I gave here is correct! Follow it exactly. –  Feb 23 '18 at 00:56
  • And there is no point helping you on your other question, since you seem to have ignored everything I have told you here. –  Feb 23 '18 at 00:59
  • And you have a view model, so using `ViewBag` is just crazy. But if you really want to use `ViewBag` for your `SelectList`, then its `@Html.EditorFor(m => m.Students, new { Countries = ViewBag.Countries })` to pass the SelectList to the template –  Feb 23 '18 at 01:02
  • sir please do not angry with me. i saw you use viewdata to bind dropdwon your code `@Html.DropDownListFor(m => m.CountryID, (IEnumerable)ViewData["Countries "], "-- Select Country--", new { ... })` so thought i may need to use viewbag or viewdata. – Monojit Sarkar Feb 23 '18 at 11:58
  • here you passed country model data to student cshtml file `@Html.EditorFor(m => m.Students, new { Countries = Model.Countries})` but i saw without passing it explicitly it is implicitly passed....how? – Monojit Sarkar Feb 25 '18 at 18:27
  • I'll add some notes in our chat session. –  Feb 25 '18 at 23:35
  • Sir thanks i read your write up in chat and understand the reason to pass model explicitly. – Monojit Sarkar Feb 26 '18 at 09:48
  • Sir i need your help to bind radio buttons when i have referred a child view in another child view from editortemplates https://stackoverflow.com/questions/48989710/asp-net-mvc-how-to-work-with-editortemplates-and-radio-buttons – Monojit Sarkar Feb 26 '18 at 13:33
  • It seem like @Html.EditorFor is designed to make edit pages for editing a single item row, not a table. – John Foll Feb 27 '23 at 20:37