首页 文章

在MVC视图中使用Knockout多次生成和跟踪相同的模板?

提问于
浏览
1

我整理了一个使用Knockoutjs的Contacts原型MVC应用程序 . 我对Knockout很新,并且想知道我的设计在达到我的最终目标时是否正确 . 我的最终目标基本上是采用传递给我的Contacts视图的MVC模型来启动并实现以下目标:

  • 将其映射到我的KO View模型 .

  • 使用Bootstrap Modal Popup输入我的联系人数据 .

  • 在成功将JSON数据发布到控制器后单击Add in Bootstrap Modal调用模板并将其显示在
    如果单击,则在div下呈现的每个模板上的

  • 编辑按钮会显示相同的模态弹出窗口以编辑模板数据 .

这是我目前所处的代码细分 .

View Code

<h2>Contacts List</h2>

    <div class="row">
        <div class="col-lg-2"></div>
        <div class="col-lg-10"><h3>KO Results</h3></div>
    </div>
    
<div class="row"> <div class="col-lg-2"></div> <div class="col-lg-10"><div id="koResults" data-bind="template: { name: 'contactSectionTmp', foreach:Contacts }"></div></div> </div> <div class="row"> <div class="col-lg-2"></div> <div class="col-lg-10"><a href="#" id="addContact" class="btn btn-sm btn-success" data-toggle="modal" data-target="#contactModal" data-bind="click: addContact"><strong>Add</strong></a></div> </div> @*I enter data in my bootstrap modal shown below and when I click "Add" the Template below appears in div element koResults with the data I just entered. This is the desired effect I'm looking for. *@ <div class="modal" id="contactModal" tabindex="-1" role="dialog" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header" style="background-color:#B8E28D; border-color: black"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <h4 class="modal-title" id="myModalLabel">Add Contact</h4> </div> <div class="form-horizontal"> <form id="contactModalForm" data-bind="with:newContact,submit:add"> <div class="modal-body"> <h4>Contact</h4> <div class="form-group"> <label class="col-sm-4 control-label">Name:</label> <div class="col-sm-8"> <input type="text" name="Name" class="form-control" data-bind="value: Name" /> </div> </div> <div class="form-group"> <label class="col-sm-4 control-label">Address:</label> <div class="col-sm-8"> <textarea rows="4" cols="50" name="Address" class="form-control" data-bind="value: Address"></textarea> </div> </div> <div class="form-group"> <label class="col-sm-4 control-label">Phone:</label> <div class="col-sm-8"> <input type="text" name="Phone" class="form-control" data-bind="value: Phone" /> </div> </div> </div> <div class="modal-footer"> <button type="submit" id="formSubmitContact" class="btn btn-success">Add</button> <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button> </div> </form> </div> </div> </div> </div> @section scripts <script type="text/javascript" src="~/Scripts/knockout-3.4.0.debug.js"></script> <script type="text/javascript" src="~/Scripts/knockout.mapping-latest.debug.js"></script> @* Knockout Template *@ <script id="contactSectionTmp" type="text/html"> <div class="row"> <div class="col-lg-3">Name:</div> <div class="col-lg-9" data-bind="text: name"></div> </div> <div class="row"> <div class="col-lg-3">Address:</div> <div class="col-lg-9" data-bind="text: address"></div> </div> <div class="row"> <div class="col-lg-3">Phone:</div> <div class="col-lg-9" data-bind="text: phone"></div> </div> </script> End Section

Controller Code

Pass in model to view here.
    public ActionResult ContactsList()
    {
        ContactsVM mData = new ContactsVM();

        mData.Contacts = new List<Contact>(){ new Contact { ID = 1, Name="Drew Lucacca", Address="782 Select St.", Phone="421-821-9101"},
            new Contact {ID = 2, Name="Kevin Rosassa", Address = "222 Potter Lane", Phone="421-982-5222" },
            new Contact {ID = 3, Name="Tim Kropp", Address = "440 PPG Place", Phone="725-434-8989"} };

        return View(mData);
    }

    [HttpPost]
    public ActionResult ContactCreate(Contact newContact)
    {

        var res = newContact;

        ContactsVM myContacts = new ContactsVM();
        myContacts.Contacts = new List<Contact>();

        myContacts.Contacts.Add(new Contact { ID = 4, Name = "Santa Claus", Address = "440 Trump Plaza", Phone = "774-489-8989" });

        return Json(myContacts);
    }

Javascript Code

`        //Main ViewModel
        function ContactsVM(data) {

            var self = this;

            var mapping = {
                'Contacts': {
                    create: function(options) {
                        return new Contact(options.data);
                    }
                }
            };

            ko.mapping.fromJS(data, mapping, self);

            self.newContact = ko.observable();

            self.addContact = function() {
                debugger;
                self.newContact(new Contact({Name: '', Address: '', Phone: ''}));
            }

            self.add = function () {
                debugger;
                var jsData = data;
                var jsData1 = ko.mapping.toJSON(self.newContact());

                $.ajax({
                    url: '@Url.Action("ContactCreate", "Home")',
                    type: 'POST',
                    data: ko.mapping.toJSON(self.newContact()),
                    dataType: 'json',
                    contentType: 'application/json; charset=utf-8',
                    success: function (jsonObject) {
                        self.contacts.push(new Contact(jsonObject));
                    }
                });

                // Close the modal.
                $('#contactModal').modal('toggle');
            };


            self.cancel = function () {

                // Close the modal.
                $('#contactModal').modal('toggle');
            };

            //self.resetForm = function (formId) {
            //    var form = $('#' + formId);
            //    form.validate().resetForm();
            //    form.get(0).reset();
            //};



};

    function Contact(data) {
        ko.mapping.fromJS(data, {}, this);
        this.isEdit = ko.observable(false);
    };


$(function () {

    var jsonModel = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model));

    var vm = new ContactsVM(jsonModel);
    ko.applyBindings(vm);

    });

Contact Entity

public class Contact
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string Phone { get; set; }
}

ContactsVM Entity

public class ContactsVM
{
    public List<Contact>  Contacts { get; set; }
}

EDIT #1 请参阅此处's the thing I know that the javascript isn' t正确并注意在javascript评论中询问您是否可以帮助我确定它是否不正确应该如何 .

我将代码移动到MVC视图底部的新位置,因为Javascript代码似乎没有找到模型 .

Javascript - Knockout - Mapping Error

JavaScript运行时错误:'push'未定义

self.contacts.push(new Contact(jsonObject)); <---这里发生错误 .

这里的任何帮助将不胜感激,我相信也会帮助其他人 .

1 回答

  • 0

    我认为根据您列出的步骤,您可能最好采用迭代方法来实现此功能 . 一次做一件事,让它工作,然后继续下一个项目 . 试图一次性解决所有问题并完全测试它真的很难 .

    First Recommendation: 使您的客户端模型反映您的服务器端模型 . 之后,事情变得更容易了 . 由于您使用的是ko映射,因此您的客户端模型设置变得更加容易:

    function ContactsVM(data) {
      var mapping = {
        'Contacts': {
          create: function(options) {
            return new Contact(options.data);
          }
        }
      };
    
      ko.mapping.fromJS(data, mapping, this);
      this.newContact = ko.observable();
    }
    
    function Contact(data) {
      ko.mapping.fromJS(data, {}, this);
      this.isEdit = ko.observable(false);
    }
    

    然后,您也可以相当轻松地创建和应用顶级视图模型:

    var vm = new ContactsVM(jsonModel);
      ko.applyBindings(vm);
    

    这为您提供了一个顶级视图模型,其中包含一个完全填充的Contacts observable数组属性 . 您可以使用模式的newContact属性添加新联系人,只需使用新的Contact实例填充它 .

    new Contact({Name:'', Address:'', Phone:''})
    

    当您将此新联系人推送到联系人数组时,DOM将自动更新以显示新联系人,因此您不需要使用您指定的“ko.renderTemplate”逻辑 . 我想你也可以根据这个observable是否有值来显示/隐藏模态 .

    Second recommendation :首先尝试使用淘汰赛,如果你不能再使用jQuery . 我不建议使用jQuery来序列化表单值 . 请记住,您可以直接访问客户端模型,因此您不再依赖于DOM . ko映射插件有一个方法unmap回到常规的JS对象 .

相关问题