Search code examples
razormodelasp.net-core-mvc

How do I define data model type for an advance group of item?


I have just begun in ASP.Net Core MVC field and there's a form of input item that confuse me a lot. In which, several items will be gathered in checkbox form. For each item checked, it will display a list of input field that related to those checked item. I don't know the proper way to define this model as well as using it in Razor page. It contains many layers of data in an insane amount of data. The amount item in my image has been reduce, their real amount is a lot more.

What it looks like on Web

enter image description here


Solution

  • From your description, it seems that you want to dynamically load the related data based on the selected Category, right? If that is the case, you could refer the following sample:

    Model: The Category and the Survey have one-to-many relationship.

    public class Category
    {
        public int CategoryId { get; set; }
        public string Name { get; set; }
        public bool IsSelected { get; set; }
    
        public List<Survey> Surveys { get; set; }
    }
    
    public class Survey
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Answer { get; set; } 
        public int CategoryId { get; set; }
        [ForeignKey("CategoryId")]
        public Category Category { get; set; }
    }
    

    Controller:

    public class TestController : Controller
    {
        private readonly ApplicationDbContext _context;
    
        public TestController(ApplicationDbContext context)
        {
            _context = context;
        }
    
        public IActionResult Index()
        {
            return View(_context.Categories.ToList());
        }
        // get the survey based on the checked category.
        [HttpPost]
        public IActionResult GetSurveyByCategory(List<int> ids)
        {
            //according the selected category to find the related data.
            var surveys = _context.Categories.Include(c => c.Surveys).Where(c => ids.Contains(c.CategoryId)).SelectMany(c => c.Surveys).ToList();
    
            //use partial view display the data and return to the main page.
            return PartialView("_PVSurvey", surveys);
        }
    }
    

    Index.cshtml: Using jQuery Ajax load partial view method to render the related surveys

    @model List<WebApplication6.Data.Category>
    
    @{
        ViewData["Title"] = "Index";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    
    <h1>Category</h1>  
    <div class="container"> 
        @foreach (var item in Model)
        {
            <div class="form-check-inline">
                <label class="form-check-label">
                    <input type="checkbox" class="form-check-input chk" value="@item.CategoryId" @(item.IsSelected ? "checked" : "")>@item.Name
                </label>
            </div> 
        }
    </div> 
    
    <div id="detailcontent" class="container" style="background-color:gainsboro">
    
    </div>
    
    @section Scripts{ 
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script>
        function GetSurveyByCategory() { 
            var category = [];
            //get the checked category id.
            $(".chk").each(function (i, e) {
                if ($(e).is(":checked"))
                    category.push(parseInt($(e).val())); 
            });  
            //use jquery to get survery
            $.ajax({
                url: '/Test/GetSurveyByCategory',
                type: 'Post',
                data: { "ids": category }, 
                traditional: true,   
                success: function (result) {
                    $('#detailcontent').html("");//clear the content
                    $('#detailcontent').html(result); //add the partial view in the index page.
                },
                error: function (xhr, status) {
                    alert(status);
                }
            });
        };
        $(function () {
            $(".chk").each(function (index, item) {
                $(item).click(function () {
                    GetSurveyByCategory();
                });
            });
            //after page loading, check whether need to load the related survey based on the checked category
            GetSurveyByCategory();
        });
    </script>
    }
    

    _PVSurvey.cshtml: use this partial view to display the related data.

    @model IEnumerable<WebApplication6.Data.Survey>
    
    <div class="row"> 
        @foreach (var item in Model)
        {
            <div class="col-3">
                <dl>
                    @Html.DisplayFor(modelItem => item.Title)
                </dl>
                <div>
                    <input asp-for="@item.Answer" />
                </div>
            </div>
        }
    </div> 
    

    The result like this:

    enter image description here

    More detail information about the relationship between entities, see:

    One-to-Many Relationship Conventions in Entity Framework Core

    Relationships

    Besides, after rendering the related data, you might want to update the related data. If that is the case, you could use refer to the following tutorials:

    Loading Related Data

    Update related data

    Jquery/Ajax to update a TABLE