PineCone
PineCone

Reputation: 2343

Dynamically generate columns with check box for each row in ASP.Net MVC

I am working two database tables where UserDetaisl table holds details about Users having one or multiple Roles and Role table holds name of the Roles. I need to generate a HTML table something similar to the picture below. Where Each role from the Role table would be shown as a column and user with assigned role would be displayed as a check box ticked for that cell. non assigned role would show unticked check box. One user can have more than one role.

enter image description here

My classes look like:

public partial class UserDetails
{
    public string username { get; set; }
    public string role { get; set; }

    public virtual Role Role1 { get; set; }
}


public partial class Role
{
    public string Role1 { get; set; }
    public virtual ICollection<UserDetails> UserDetails { get; set; }
}

Thought of creating a ViewModel which would show the Role selection.

public class RoleSelectionViewModel
{
    public bool Selected { get; set; }
    public bool NotSelected { get; set; }
    public virtual Role Role1 { get; set; }
}

Not sure how to put all these toegther to generate the columns on the fly.

currentlty the following Controller method only lists all the users from the table with associated role.

    public ActionResult Index()
    {
        var userDetails = db.UserDetails.Include(u => u.Role1);
        return View(userDetails .ToList());
    }

Upvotes: 0

Views: 1057

Answers (2)

Focki
Focki

Reputation: 150

If you want the Users to have several Roles you will have to update your UserDetails class to have a Collection of Roles instead of just one.

Then update your RoleSelectionViewModel like

public class RoleSelectionViewModel
{
    public ICollection<Role> Roles { get; set; } //list of all roles existing in your db for the columns
    public ICollection<UserDetails> Users {get; set;} //list of all users for which you want to set roles
}

and then in the controller

public ActionResult Index()
{
    var userDetails = db.UserDetails.Include(u => u.Roles).ToList();
    var allRoles = db.Roles.ToList();
    var viewModel = new RoleSelectionViewModel();
    viewModel.Users = userDetails;
    viewModel.Roles = allRoles;
    return View(viewModel);
}

then you can Iterate over the Roles for the columns and over the users for the Rows and set the Checkboxes if the user has the role of the actual column.

Upvotes: 0

user3559349
user3559349

Reputation:

Your UserDetails class contains properties string role and virtual Role Role1 which means that a UserDetails can only contain one role. In order to select and assign multiple roles, then you model would need a public virtual ICollection<Role> Roles { get; set; } property.

In order to generate the view you want, you need to create view models

public class UserVM
{
    public string UserName { get; set; }
    public List<RoleVM> Roles { get; set; }
}
public class RoleVM
{
    public string RoleName { get; set; }
    public bool IsSelected { get; set; }
}

and your view would be

@model List<UserVM>
....
@using (Html.BeginForm())
{
    <table>
        <thead>....</thead>
        <tbody>
            @for(int i = 0; i < Model.Count; i++)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(m => m[i].UserName)
                        @Html.HiddenFor(m => m[i].UserName)
                    </td>
                    @for(int j = 0; j < Model[i].Roles.Count; j++)
                    {
                        <td>
                            @Html.HiddenFor(m => m[i]Roles[j].RoleName)
                            @Html.CheckBoxFor(m => m[i]Roles[j].IsSelected)
                        </td>
                    }
                </tr>
            }
        </tbody>
    </table>
    <input type="submit" ... />
}

Since the models you have shown are not correct for what your wanting to achieve, and I suspect you will need to makes changes to you data base (you will need tables for Users, Roles and UserRoles), the following controller code is a suggestion of what it should look like

public ActionResult Edit()
{
    var roles = db.Roles; // get the collection of all roles
    var users = db.Users.Include(x => x.Roles); // get the collection of all users including their selected roles
    List<UserVM> model = new List<UserVM>();
    foreach (var user in users)
    {
       UserVM u = new UserVM
       {
           UserName = user.username,
           Roles = roles.Select(x => new RoleVM
           {
               RoleName = x.Role1
           }).ToList()
       }
       .... // set the IsSelected property of each RoleVM based existing roles
       model.Add(u);
    }
    return View(model);
}
[HttpPost]
public ActionResult Edit(List<UserVM> model)
{
    // Get the selected roles for each user
    foreach (UserVM user in Model)
    {
        var selectedRoles = user.Roles.Where(x =>x.IsSelected);

Upvotes: 1

Related Questions