将KnockoutJS模型发布到MVC控制器,列表<T>中的列表<T>为空

时间:2019-07-03 07:52:04

标签: asp.net-mvc knockout.js

我对KnockoutJS的经验很少,所以请多多包涵。

我有一个想要开始工作的基本示例,因此可以将其扩展到我的项目中。

在此示例中,单击按钮,并调用AddSku方法以返回带有List的QuoteLine数据。

但是,如图所示,BomDetails为空:

BomDetails Empty

型号:

public class QuoteViewModel
{
    public int Id { get; set; }
    public string QuoteName { get; set; }
    public IList<QuoteLine> QuoteLines { get; set; }
}

public class QuoteLine
{
    public string Description { get; set; }
    public string Sku { get; set; }

    public IList<BomDetail> BomDetails = new List<BomDetail>();
}

public class BomDetail
{
    public string Name { get; set; }
}   

控制器方法:

[HttpGet]
public ActionResult CreateQuote()
{
    QuoteViewModel quote = new QuoteViewModel();
    quote.Id = 10;
    quote.QuoteName = "Test Create Quote";
    quote.QuoteLines = new List<QuoteLine>();

    return View(quote);
}

[HttpPost]
public ActionResult CreateQuote(QuoteViewModel viewModel)
{
    if (ModelState.IsValid)
    {

    }

    return RedirectToAction("CreateQuote");
}

[HttpGet]
public JsonResult AddSku()
{
    QuoteLine line = new QuoteLine();
    line.BomDetails = new List<BomDetail>();

    line.Sku = "TestSku";
    line.Description = "TestDescription";

    line.BomDetails.Add(new BomDetail
    {
       Name = "BOM Detail 1"         
    });

    line.BomDetails.Add(new BomDetail
    {
        Name = "BOM Detail 2",
    });

    return Json(line, JsonRequestBehavior.AllowGet);
}

视图:

@model EngineeringAssistantMVC.ViewModels.QuoteViewModel

<script src="~/Scripts/knockout.mapping-latest.js"></script>

<div class="container-fluid">

<h2>Create Quote</h2>

@using (Html.BeginForm("CreateQuote", "Test", FormMethod.Post, new { @id = "createQuoteForm", @class = "form-horizontal", role = Model, enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.HiddenFor(m => m.Id)
    @Html.HiddenFor(m => m.QuoteName)

    <h3>Quote Lines</h3>

    <table class="table master-detail-table" id="receiving-table">
        <thead>
            <tr>
                <th>SKU</th>
                <th>Description</th>
            </tr>
        </thead>
        <tbody data-bind="foreach: QuoteLines">        
            <tr>
                <td>
                    <input class='form-control' data-bind='value: $data.Sku, attr: { name: "QuoteLines[" + $index() + "].Sku" } ' type='text' readonly='readonly' />
                </td>
                <td>
                    <input class='form-control' data-bind='value: $data.Description, attr: { name: "QuoteLines[" + $index() + "].Description" } ' type='text' readonly='readonly' />
                </td>             
            </tr>
            <tr class="detail-row">
                <td colspan="7">
                    <table class="table">
                        <thead>
                            <tr>
                                <th>Name</th>
                            </tr>
                        </thead>
                        <tbody data-bind="foreach: BomDetails">
                            <tr>
                                <td>
                                    <input class='form-control' data-bind='value: $data.Name, attr: { name: "BomDetails[" + $index() + "].Name" } ' type='text' readonly='readonly' />
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </td>
            </tr>
        </tbody>

    </table>

    <h3>Add Sku from Db</h3>
        <div class="row">
            <div class="col-sm-2">
                <input type="button" value="Add Sku" id="btnAddSku" class="btn btn-satcom-primary btn-wider" />
            </div>
        </div>

        <h3>Submit</h3>
        <div class="row">
            <div class="col-sm-1">
                <input type="submit" value="Submit" class="btn btn-satcom-primary btn-wider" id="btnSubmit" />
            </div>
        </div>
}
</div>

<script type="text/javascript">
$(function () {

    quoteViewModel = new QuoteViewModel();
    ko.applyBindings(quoteViewModel);

    $('#btnAddSku').off().on('click', function () {
        AddFromDb();
    });
});

function QuoteViewModel() {
    var self = this;

    self.Id = ko.observable('@Model.Id');
    self.QuoteName = ko.observable('@Model.QuoteName');

    self.QuoteLines = ko.observableArray([]);

    self.AddQuoteLine = function (sku, description, bomDetails) {
        self.QuoteLines.push(new QuoteLineViewModel(sku, description, bomDetails));
    }
}

function QuoteLineViewModel(sku, description, bomDetails) {
    var self = this;
    self.Sku = sku;
    self.Description = description;

    self.BomDetails = ko.observableArray([]);

    $.each(bomDetails, function (index, item) {
        self.BomDetails.push(new BomDetailViewModel(item.Name));
    });     
}

function BomDetailViewModel(name) {
    var self = this;
    self.Name = name;
}

function AddFromDb() {
    $.ajax({
        type: "GET",
        url: '@Url.Action("AddSku", "Test")',
        success: function (line) {
            window.quoteViewModel.AddQuoteLine(line.Sku, line.Description, line.BomDetails);               
        }
    });
}

我已经尝试了很多方法来填充它,但无法弄清楚问题出在哪里,但是我希望这只是我正在做或没有做的愚蠢的事情。

我也尝试过使用ko.mapping,但是我也无法正常工作。

1 个答案:

答案 0 :(得分:0)

我设法使这项工作奏效,因此希望它将对以后的其他人有所帮助。

我删除了@Using(Html.BeginForm)

我将提交按钮更改为普通按钮,并将数据绑定添加到功能

        <input type="button" value="Submit" class="btn btn-satcom-primary btn-wider" id="btnSubmit" data-bind="click:SaveToDatabase" />

SaveToDatabase函数:

self.SaveToDatabase = function () {
        var dataToSend = ko.mapping.toJSON(self);
        $.ajax({
            type: "POST",
            url: '@Url.Action("CreateQuote", "Test")',
            contentType: 'application/json',
            data: dataToSend,
            success: function (data) {
            },
            error: function (err) {
                console.log(err.responseText);
            }
        });
    }

这正确地将所有数据发送到控制器。