如何在剃刀视图中动态地将数据添加到视图模型的List属性中?

问题描述:

我有一个客户需要能够创建候选人.候选人可以具有许多资格(资格是具有4个属性的模型).客户需要能够在创建页面上向员工添加N个资格.

I have a client needs to be able to create candidates. Candidates can have many qualifications (qualifications is model with 4 properties). The client needs to be able to add N numbers of qualifications to the employee on the creation page.

查看模型

public class CreateCandidateViewModel
{
    [DisplayName("First Name"), Required]
    public string FirstName { get; set; }

    [DisplayName("Last Name"), Required]
    public string LastName { get; set; }

    [DisplayName("Email Address"), Required]
    public string Email { get; set; }

    [DisplayName("Phone Number"), Required]
    public string Phone { get; set; }

    [DisplayName("Zip Code"), Required]
    public int ZipCode { get; set; }

    public List<Qualification> Qualifications { get; set; }
}

资格模型

public class Qualification
{
    [Key]
    public int Id { get; set; }
    public int QualificationTypeId { get; set; }
    public string Name { get; set; }
    public DateTime DateStarted { get; set; }
    public DateTime DateCompleted { get; set; }

    [ForeignKey("QualificationTypeId")]
    public virtual QualificationType Type { get; set; }
}

我不知道如何解决这个问题.我当时在考虑先创建候选人,然后再将客户发送到另一个可以让客户添加资格等的视图.

I have no idea how to approach this problem. I was thinking of creating the candidate first and then sending the client to another view where the client can add qualifications and so on.

斯蒂芬(Stephen)在评论中提到,如果要使用户保持在同一页面上,则可能需要使用javascript或jquery来完成此操作.

Stephen mentioned in a comment that you will likely need to use javascript or jquery to accomplish this if you want to keep your user on the same page.

我假设您的后控制器期望CreateCandidateViewModel

I am assuming your post controller is expecting a CreateCandidateViewModel

只要您的模型具有对象列表的属性,就可以进行模型绑定,只要提交表单时输入的命名正确即可.关键是索引输入中的名称:

It is possible to do model binding when your model has a property of a list of objects, so long as the naming on the inputs is correct when the form is submitted. The key is indexing the names on the inputs:

<input type="text" name="Qualifications[0].Id" />
<input type="text" name="Qualifications[0].QualificationTypeId" />
<input type="text" name="Qualifications[0].Name" />
<input type="text" name="Qualifications[0].DateStarted" />
<input type="text" name="Qualifications[0].DateCompleted" />
<input type="text" name="Qualifications[1].Id" />
<input type="text" name="Qualifications[1].QualificationTypeId" />
<input type="text" name="Qualifications[1].Name" />
<input type="text" name="Qualifications[1].DateStarted" />
<input type="text" name="Qualifications[1].DateCompleted" />

这将在提交时正确绑定到您的模型.在添加限定词"后删除它们时,请务必重置索引,否则列表中可能会出现空对象或缺少对象.在使用JQuery和正则表达式之前,我已经成功地做到了这一点.

This will correctly bind to your model on submit. Be mindful of resetting the indexies when removing a "qualification" after it was added, or you may get null objects in your list, or missing objects. I've done this successfully before with JQuery and regular expressions.

如果要使用Ajax方式,可以创建局部视图并使用AJAX进行调用.

If you want to go the Ajax way, you could create a partial view and call that using AJAX.

public ActionResult QualificationsPartial(Int32 Index)
{
    return PartialView(model:Index);
}

部分视图

@model Int32

<input type="text" name="Qualifications[@Model.ToString()].Id" />
<input type="text" name="Qualifications[@Model.ToString()].QualificationTypeId" />
<input type="text" name="Qualifications[@Model.ToString()].Name" />
<input type="text" name="Qualifications[@Model.ToString()].DateStarted" />
<input type="text" name="Qualifications[@Model.ToString()].DateCompleted" />

主视图上的Ajax

var QualificationIndex = parseInt(1);  // 1 because we already have 0 loaded

$("#AddQualificationElement").click(function () {

    $.ajax({
        cache: false,
        type: "GET",
        url: "/MyController/QualificationsPartial",
        data: { 
           Index: QualificationIndex
        },
        success: function (data) {
            // data will be the html from the partial view
            $("#QualificationsContainer").append(data);
        },
        error: function (xhr, ajaxOptions, thrownError) {
            // Handle the error somehow
        }
    }); // end ajax call
}); // end AddQualificationElement click event