我整理了一个使用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">×</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 回答
我认为根据您列出的步骤,您可能最好采用迭代方法来实现此功能 . 一次做一件事,让它工作,然后继续下一个项目 . 试图一次性解决所有问题并完全测试它真的很难 .
First Recommendation: 使您的客户端模型反映您的服务器端模型 . 之后,事情变得更容易了 . 由于您使用的是ko映射,因此您的客户端模型设置变得更加容易:
然后,您也可以相当轻松地创建和应用顶级视图模型:
这为您提供了一个顶级视图模型,其中包含一个完全填充的Contacts observable数组属性 . 您可以使用模式的newContact属性添加新联系人,只需使用新的Contact实例填充它 .
当您将此新联系人推送到联系人数组时,DOM将自动更新以显示新联系人,因此您不需要使用您指定的“ko.renderTemplate”逻辑 . 我想你也可以根据这个observable是否有值来显示/隐藏模态 .
Second recommendation :首先尝试使用淘汰赛,如果你不能再使用jQuery . 我不建议使用jQuery来序列化表单值 . 请记住,您可以直接访问客户端模型,因此您不再依赖于DOM . ko映射插件有一个方法unmap回到常规的JS对象 .