在knockout mvc中向observable数组添加一个新对象

时间:2013-08-09 15:40:05

标签: asp.net-mvc knockout.js observablecollection knockout-mapping-plugin

我正在使用knockout映射来帮助将服务器端对象映射到JSON。我有一个包含大量集合的对象,因此我不想在javascript中手动重新创建和映射每个部分。所以,我正在使用knockout-mapping为我做这件事。

我遇到了问题,所以我决定尝试一个简单的例子,所以这就是我对ASP.NET MVC应用程序的看法:

C#型号:

    public class Vaccinations
{
    public string Vaccination { get; set; }
    public System.DateTime VaccinationDate { get; set; }
}

public class Dog
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Dog()
    {
        this.Vaccinations = new System.Collections.Generic.List<Vaccinations>();
    }

    public System.Collections.Generic.List<Vacinations> Vacinations { get; set; }
}

如您所见,每只狗都有一份他们可能会或可能没有的疫苗接种清单。

在我的控制器中,我创建并返回一个预先填充的Dog对象:

        public ActionResult Load()
    {
        Dog rambo = new Dog
        {
            Name = "Rambo",
            Age = 5
        };

        rambo.Vacinations = new System.Collections.Generic.List<Vacinations> {
            new Vacinations { Vacination = "Rabies", VacinationDate = DateTime.Now.AddYears(-1) },
            new Vacinations { Vacination = "Mumps", VacinationDate = DateTime.Now.AddYears(-2) }
        };

        return Json(rambo, JsonRequestBehavior.AllowGet);
    }

在我看来(Index.cshtml),我设置它来显示狗和它的疫苗接种列表。我想允许用户点击Add Vaccination按钮向系列中添加一个新行并允许他们输入数据。

同样,我正在使用knockout.mapping为我做映射。在javascript部分,这就是我所拥有的:

    var ViewModel = function (data) {
    var self = this;
    ko.mapping.fromJS(data, {}, self);

    self.isValid = ko.computed(function () {
        return self.Name().length > 3;
    });

    // Operations
    self.save = function () {
        $.ajax({
            url: "Dog/Save",
            type: "post",
            contentType: "application/json",
            data: ko.mapping.toJSON(self),
            success: function (response) {
                alert(response.Status);
            }
        });
    };

    self.addVaccination = function () {
        self.Vaccinations.push(new self.Vaccination());  // <--- This doesn't work and I know why, so how do I do this?
    }
};

$(function () {
    $.getJSON("Dog/Load", null, function (data) {
        ko.applyBindings(new ViewModel(data));
    });
});

我的问题围绕我添加到ViewModel对象的“addVaccination”函数。如何指定一个新的“Vaccination”对象而不必在Javascript中“编码”一个?这就是我使用淘汰映射的全部原因,所以我不必这样做。但是,我没有看到任何其他方式。

有没有办法从Vaccinations observable数组访问基础Vaccination对象,这样我可以创建一个新的?

然后最后一个问题是,如何将其传回我的控制器?我不确定这是否有效。

1 个答案:

答案 0 :(得分:0)

你不能直接。但是你可以做的是在服务器端定义一个Vaccination实例并将其作为默认实例返回。

因此,您需要返回旧数据和默认实例。

public ActionResult Load()
{
    ...
    var data = new {
         defaultVacination = new Vacination(),
         rambo =  rambo,
    };
    return Json(data , JsonRequestBehavior.AllowGet);
}

在客户端,您会收到相同的数据和默认实例。

var ViewModel = function (data) {
    var self = this;    
    ko.mapping.fromJS(data.rambo, {}, self);
    var defaultInstance =  data.defaultVacination;        
    ...      
     self.addVaccination = function () {
        // clone the default instance.
        self.Vaccinations.push(ko.utils.extend({}, defaultInstance));  

}

我希望它有所帮助。