Home Table with dynamic columns mvc
Reply: 0

Table with dynamic columns mvc

Андрій Петрук
1#
Андрій Петрук Published in 2017-11-14 13:20:48Z

I'm developing a ASP.MVC application for editing table with unknown count of rows and columns

I get it in "Details" view, but cannot get data from "Creating view"

My answer table contains FK to Item(it's "question"), Attribute(its ColumnHeader) and Order(Document) One Order has many "Questions" with many "Answer"

My Order model:

    public partial class Order
{
    public Order()
    {
        Answers = new HashSet<Answer>();
    }

    [Key]
    [Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int MasterFID { get; set; }

    [Key]
    [Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ID { get; set; }

    public int? DocTypeID { get; set; }


    public virtual ICollection<Answer> Answers { get; set; }
    public virtual Agent MasterAgent { get; set; }
    public virtual DocType DocType { get; set; }

My Answer model :

public partial class Answer
{
    [Key]
    [Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int OrderID { get; set; }

    [Key]
    [Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int MasterFid { get; set; }

    [Key]
    [Column(Order = 2)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ItemId { get; set; }

    [Key]
    [Column(Order = 3)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int AttrId { get; set; }

    [StringLength(255)]
    public string Value { get; set; }


    public virtual Order Order { get; set; }

    public virtual Item Item { get; set; }

    public virtual Attribute Attribute { get; set; }

}

For display it in Details I create next ViewModels:

 public class OrderViewModel
{
    public Order Order { get; set; }
    public List<QuestionViewModel> Questions { get; set; }
}
public class QuestionViewModel
{
    public QuestionViewModel() { }
    public QuestionViewModel(Item item, List<AnswerViewModel> answers)
    {
        Item = item;
        Answers = answers;
    }
    public Item Item { get; set; }
    public List<AnswerViewModel> Answers { get; set; }
}
public class AnswerViewModel
{
    public Attribute Attribute { get; set; }
    public string Value { get; set; }
}

In My OrderController method "Details" I do next, and it work fine:

        public async Task<ActionResult> Details(int? orid)
    {

        var user = await GetCurrentUserAsync();
        var order = user.Orders.FirstOrDefault(o => o.ID == orid);

        var answers = order.Answers.ToList();
        var items = answers.GroupBy(g => g.Item).Select(group => group.Key).ToList();//Rows Headers;


        var questions = new List<QuestionViewModel>();

        foreach (var question in items)
        {
            var q = new QuestionViewModel()
            {
                Item = question,
                Answers = new List<AnswerViewModel>()
            };
            var itemAnswers = answers.Where(w => w.ItemId == q.Item.ID).ToList();
            foreach (var answer in itemAnswers)
            {
                q.Answers.Add(new AnswerViewModel()
                {
                    Attribute = answer.Attribute,// await db.Attributes.FirstOrDefaultAsync(a => a.AttrID == answer.AttrId),
                    Value = answer.Value
                });
            }
            questions.Add(q);

        }
        var orderViewModel = new OrderViewModel()
        {
            Order = order,
            Questions = questions
        };
        return View(orderViewModel);
    }

And in View Details:

    <table class="table">
    <tr>
        <td>Вопрос</td>

        @foreach (var item in Model.Questions.SelectMany(x => x.Answers).GroupBy(x => x.Attribute).Select(k => k.Key).OrderBy(o => o.AttrID))
        {

            <td> @Html.DisplayFor(m => item.AttrName) </td>
        }
    </tr>
    @foreach (var item in Model.Questions)
    {
        <tr>
            <td> @Html.DisplayFor(i => item.Item.ShortName)</td>
            @foreach (var answer in item.Answers.OrderBy(o => o.Attribute.AttrID))
            {
                <td>@Html.DisplayFor(e => answer.Value)</td>
            }
        </tr>
    }
</table>

But when I try it in "Create" - I dont have values in "Attribute" and "Item" property. My Create method in OrderController:

        public async Task<ActionResult> Create(int? outletID, int? dtid )
    {

        var user = await GetCurrentUserAsync();
        var docitems = await db.DocTypes.Include(x => x.Items).FirstOrDefaultAsync(x => x.DocTypeID == dtid);//Elements in curent document type

        var headers = docitems.Attributes.OrderBy(x => x.Sort);
        var items = docitems.Items.OrderBy(x => x.Sort); //property from DataBase for sort 

        var questions = new List<QuestionViewModel>();
        foreach (var question in items)
        {
            var q = new QuestionViewModel()
            {
                Item = question,
                Answers = new List<AnswerViewModel>()
            };

            foreach (var answer in headers)
            {
                q.Answers.Add(new AnswerViewModel()
                {
                    Attribute = answer,
                    Value = null
                });
            }
            questions.Add(q);

        }
        var orderViewModel = new OrderViewModel()
        {
            Order = new Order()
            {
                MasterFID = user.FId,
                OutletID = outletID,
                Outlet = await db.Outlets.FirstOrDefaultAsync(o => o.fID == outletID),
                MasterAgent = user
            },
            Questions = questions
        };
        return View(orderViewModel);
    }

My "Create" View:

        <table class="table">
        <tr>
            <td>Вопрос</td>

            @for (var item = 0; item<  Model.Questions.SelectMany(x => x.Answers).GroupBy(x => x.Attribute).Select(k => k.Key).OrderBy(o => o.AttrID).Count();item++)
            {

                <td> @Html.DisplayFor(m => Model.Questions.SelectMany(x => x.Answers).GroupBy(x => x.Attribute).Select(k => k.Key).OrderBy(o => o.AttrID).ToList()[item]. AttrName) </td>
            }
        </tr>

        @for (var i = 0; i < Model.Questions.Count;i++)
        {
            <tr>
                <td> @Html.DisplayFor(item => Model.Questions[i].Item.ShortName)</td>

                @for (var j = 0; j< Model.Questions[i].Answers.Count;j++)
                {
                    <td>@Html.EditorFor(e => Model.Questions[i].Answers[j].Value, new { htmlAttributes = new { @class = "form-control" } })</td>
                }
            </tr>
        }
    </table>

And after I click on "Submit" In my ViewModel properties "Item" and "Attribute" is null, but in "Value" i have data. What is the correct way to do this?

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.302233 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO