如何将动态加载的局部视图与父模型绑定

时间:2015-03-06 11:58:14

标签: c# asp.net-mvc asp.net-mvc-4 knockout.js

我目前正在使用“部分”视图向表中添加动态项。

该表包含在Wizard中,该向导使用knockoutjs绑定数据。

目前,部分视图已成功添加。但是,在“部分”视图中输入的值不会绑定回主模型。

我搜索SO和网络寻找解决方案,但找不到任何解决方案。

我的部分观点:

@model Question.Models.LiabilityModel

<tr>
@using (@Html.BeginCollectionItem("Liabilities")) {
    <td>
        @Html.DropDownListFor(model => model.Type, Model.Types, new { @class = "form-control selectpicker", id = "" })
    </td>
    <td>
        @Html.TextBoxFor(model => model.Name, new { @class = "form-control", id = "" })
    </td>
    <td>
        @Html.TextBoxFor(model => model.Balance, new { @class = "form-control auto", id = "" })
    </td>
    <td>
        @Html.TextBoxFor(model => model.Payment, new { @class = "form-control auto", id = "" })
    </td>
    <td>
        @Html.TextBoxFor(model => model.Interest, new { @class = "form-control", id = "", @type = "number" })
    </td>
    <td>
        @Html.TextBoxFor(model => model.Teams, new { @class = "form-control", id = "", @type = "number" })
    </td>
    <td>
        @Html.TextBoxFor(model => model.Tenure, new { @class = "form-control", id = "", @type = "number" })
    </td>
    <td>
        <button class="btn btn-primary remove-button" type="button" data-id="@Model.ID">
            <span class="glyphicon glyphicon-trash"></span>
        </button>
    </td>
}

表:

 <table id="LibList" class="table table-responsive table-condensed table-striped">
            <thead>
                <tr>
                    <th style="width: 150px;">
                        @Html.DisplayNameFor(model => model.Step3.Liabilities[0].Types)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Step3.Liabilities[0].Name)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Step3.Liabilities[0].Balance)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Step3.Liabilities[0].Payment)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Step3.Liabilities[0].Interest)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Step3.Liabilities[0].Teams)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Step3.Liabilities[0].Tenure)
                    </th>
                    <th>
                        Delete
                    </th>
                </tr>
            </thead>
            <tbody>
                @for (var i = 0; i < Model.Step3.Liabilities.Count; i++) {
                    Html.RenderPartial("_LibListItem", Model.Step3.Liabilities[i]);
                }
            </tbody>
        </table>

第一次加载页面时会添加现有项目。然后,用户可以稍后添加更多动态添加到表中的项目。

是否已将项目添加到表格中,我希望新项目添加到:

Model.Step3.Liabilities

回帖。

添加功能:

 $('.add-button').click(function () {
        var action = "/QuestionWizard/AddRow";
        $.ajax({
            url: action,
            cache: false,
            success: function (result) {
                $("#LibList").find("tbody").append($(result));
                $("#LibList").find("tbody").find('.selectpicker').last().selectpicker();
            }
        });
    });

添加操作:

 public ActionResult AddRow() {
        LiabilityModel lib = new LiabilityModel();
        try {
            if (LiabilitySessionState.Count == 0) {
                LiabilitySessionState = ((QuestionWizardViewModel)this.ViewModelSessionState).Step3.Liabilities;
            }
            lib.ID = LiabilitySessionState.LastOrDefault().ID + 1;
            LiabilitySessionState.Add(lib);
        } catch (Exception) {
            return Json(null);
        }
        return PartialView("_LibListItem", lib);
    }

我的模特:

public class WizardViewModelThirdStep : ModelBase {


        [Display(Name = "Liabilities")]
        public List<LiabilityModel> Liabilities { get; set; }

        public void getInitialItems() {
            Liabilities = new List<LiabilityModel>();

            //initial item 
            LiabilityModel model = new LiabilityModel();
            model.ID = 1;
            Liabilities.Add(model);
        }

    }
public class LiabilityModel : ModelBase {

    public int ID { get; set; }

    [Display(Name = "Type", Prompt = "Type")]
    public List<SelectListItem> Types { get; set; }

    public LIA Type { get; set; }

    [DisplayFormat(ConvertEmptyStringToNull = false)]
    [Display(Name = "Name of Institution.", Prompt = "Name of Institution.")]
    public string Name { get; set; }

    [Display(Name = "Balance ($).", Prompt = "Balance ($).")]
    [DataType(DataType.Currency)]
    public decimal Balance { get; set; }

    [Display(Name = "Payment ($).", Prompt = "Payment ($).")]
    [DataType(DataType.Currency)]
    public decimal Payment { get; set; }

    [Display(Name = "Interest (%).", Prompt = "Interest (%).")]
    public decimal Interest { get; set; }

    [Display(Name = "Teams", Prompt = "Teams")]
    public decimal Teams { get; set; }

    [Display(Name = "Tenure", Prompt = "Tenure")]
    public decimal Tenure { get; set; }

    public LiabilityModel() {
        ID = 0;
        Types = new List<SelectListItem>();
    }

}

这些是回发方法:

protected override void ProcessToNext(WizardViewModel model) {
        ((QuestionWizardViewModel)model).PageTitle = GetDisplayName(typeof(QuestionWizardViewModel), "Step" + model.StepIndex); 
    }

    protected override void ProcessToPrevious(WizardViewModel model) {
        ((QuestionWizardViewModel)model).PageTitle = GetDisplayName(typeof(QuestionWizardViewModel), "Step" + model.StepIndex);
    }

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

您不应为每个项目渲染部分内容。您应该为整个列表呈现它,MVC将负责重复它并正确索引输入字段。

因此,您应将PartialView内容移至EditorTemplate,然后在表单中使用:

<tbody>
    @Html.EditorFor(Model.Step3.Liabilities)   
</tbody>

请记住,您需要为一个项创建模板,并在整个列表中使用此模板(如上所述)。

答案 1 :(得分:0)

我的最终解决方案:

<tbody data-bind="template: { name: 'LibRowTemplate', foreach: Model.Step3.Liabilities }"></tbody>

模板:

<script type="text/html" id="LibRowTemplate">
<tr>
    <td>
        <select class="form-control selectpicker" data-bind="value: SelectedType, uniqueName: true">
            <option value="NONE">Select a Type</option>
            <option value="Loan">Loan</option>
            <option value="Investment">Investment</option>
            <option value="Others">Others</option>
        </select>
    </td>
    <td>
        <input class="form-control" data-bind="value: Name, uniqueName: true" />
    </td>
    <td>
        <input class="form-control" data-bind="value: Balance, uniqueName: true" />
    </td>
    <td>
        <input class="form-control" data-bind="value: Payment, uniqueName: true" />
    </td>
    <td>
        <input class="form-control" data-bind="value: Interest, uniqueName: true" />
    </td>
    <td>
        <input class="form-control" data-bind="value: Teams, uniqueName: true" />
    </td>
    <td>
        <input class="form-control" data-bind="value: Tenure, uniqueName: true" />
    </td>
    <td>
        <button class="btn btn-primary remove" type="button">
            <span class=" glyphicon glyphicon-trash"></span>
        </button>
    </td>
</tr>

淘汰ModelView:

self.AddLib = function () {
            self.Model.CurrentStep().Liabilities.push({ SelectedType: "", Name: "", Balance: "0", Payment: "0", Interest: "0", Teams: "0", Tenure: "0" });
        }

self.DelLib = function (element) {
            self.Model.CurrentStep().Liabilities.remove(element);
        }

 $("#tablelib").delegate(".remove", "click", function () {
        vm.DelLib(ko.dataFor(this));
    });

添加按钮:

  <button type="button" class="btn btn-primary" data-bind="event:{ click: AddLib }">
                <span class="glyphicon glyphicon-plus"></span> Add New
            </button>