赏金
它已经一段时间,我仍然有一对夫妇的悬而未决的问题。 我希望通过加入悬赏也许这些问题将得到回答。
- 如何使用与knockout.js HTML辅助
为什么需要文档准备,使其工作(更多信息请参见第一次编辑)
我怎么做这样的事,如果我使用我的观点车型淘汰赛映射? 由于我没有因映射功能。
function AppViewModel() { // ... leave firstName, lastName, and fullName unchanged here ... this.capitalizeLastName = function() { var currentVal = this.lastName(); // Read the current value this.lastName(currentVal.toUpperCase()); // Write back a modified value };
我想,就好像用户取消请求,我希望能够回到过去的值用比如我希望能够回滚观测插件。 从我的研究,这似乎被人喜欢制作插件来实现editables
如何,如果我使用映射我使用类似的东西? 我真的不想去,我有我的观点手动映射是我每个MVC VIEWMODE字段映射到一个KO模型字段,因为我想少内嵌JavaScript作为可能的,只是好像双重的工作,这是一个方法为什么我喜欢的映射。
我很担心,使这项工作容易(通过映射)我会失去很多KO电源,但在另一方面,我很担心,手动映射将只是一个大量的工作,会让我的看法包含了太多的信息和有可能成为在未来难以维持(说,如果我在MVC模式删除属性我也必须将它在KO视图模型)
原贴
我使用asp.net的MVC 3,我寻找到淘汰赛,因为它看起来很酷,但我有一个很难弄清楚它是如何工作与asp.net的MVC特别是查看模型。
对我来说,现在我做这样的事情
public class CourseVM
{
public int CourseId { get; set; }
[Required(ErrorMessage = "Course name is required")]
[StringLength(40, ErrorMessage = "Course name cannot be this long.")]
public string CourseName{ get; set; }
public List<StudentVm> StudentViewModels { get; set; }
}
我想有一个虚拟机有类似CourseName一些基本特性,它会在它上面的一些简单的验证。 如果需要虚拟测量模型可能包含其他视图模型中它。
然后我就通过这个虚拟机视图中,我会用HTML助手来帮我把它显示给用户。
@Html.TextBoxFor(x => x.CourseName)
我可能有一些foreach循环或东西来获取数据了学生视图模型的集合。
然后,当我将提交表单,我会用jQuery和serialize array
,并将其发送到将其绑定回视图模型控制器的操作方法。
随着knockout.js它是所有不同的,因为你现在得到的ViewModels它和所有的例子我看到他们不使用HTML辅助。
你如何使用MVC的这些特点2与knockout.js?
我发现这个视频 ,并简要地(视频@ 18:48的最后几分钟)进入的方式基本上由具有有knockout.js视图模型是获取视图模型分配值的内嵌脚本使用的ViewModels。
这是做它的唯一途径? 如何在我的用具有它的ViewModels的集合的例子吗? 我必须有一个foreach循环或东西来提取所有的值并把它分配到淘汰赛?
至于HTML辅助视频说他们一无所知。
这些都是2个区是混淆了赫克了我本就不多的人似乎谈论它,它让我感到困惑的初始值,一切是如何得到的视图当过例子只是一些硬编码值例子的。
编辑
我想什么了Darin季米特洛夫曾建议,这似乎工作(我不得不作出一些改变他的代码虽然)。 不知道为什么,我不得不使用文件准备好,但不知何故一切都还没有准备好,没有它。
@model MvcApplication1.Models.Test
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
<script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
<script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
<script type="text/javascript">
$(function()
{
var model = @Html.Raw(Json.Encode(Model));
// Activates knockout.js
ko.applyBindings(model);
});
</script>
</head>
<body>
<div>
<p>First name: <strong data-bind="text: FirstName"></strong></p>
<p>Last name: <strong data-bind="text: LastName"></strong></p>
@Model.FirstName , @Model.LastName
</div>
</body>
</html>
我不得不将其套在一个jQuery文档准备,使其工作。
我也得到这样的警告。 不知道这是怎么一回事。
Warning 1 Conditional compilation is turned off -> @Html.Raw
所以我有一个起点,我想至少在我做多一些玩耍以及如何工作将更新。
我试图去通过互动教程,但使用一个视图模型来代替。
不知道如何解决这些部件还
function AppViewModel() {
this.firstName = ko.observable("Bert");
this.lastName = ko.observable("Bertington");
}
要么
function AppViewModel() {
// ... leave firstName, lastName, and fullName unchanged here ...
this.capitalizeLastName = function() {
var currentVal = this.lastName(); // Read the current value
this.lastName(currentVal.toUpperCase()); // Write back a modified value
};
编辑2
我已经能够找出第一个问题。 没有关于第二个问题的线索。 然而,尽管。 任何人有什么想法?
@model MvcApplication1.Models.Test
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
<script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
<script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
<script type="text/javascript">
$(function()
{
var model = @Html.Raw(Json.Encode(Model));
var viewModel = ko.mapping.fromJS(model);
ko.applyBindings(viewModel);
});
</script>
</head>
<body>
<div>
@*grab values from the view model directly*@
<p>First name: <strong data-bind="text: FirstName"></strong></p>
<p>Last name: <strong data-bind="text: LastName"></strong></p>
@*grab values from my second view model that I made*@
<p>SomeOtherValue <strong data-bind="text: Test2.SomeOtherValue"></strong></p>
<p>Another <strong data-bind="text: Test2.Another"></strong></p>
@*allow changes to all the values that should be then sync the above values.*@
<p>First name: <input data-bind="value: FirstName" /></p>
<p>Last name: <input data-bind="value: LastName" /></p>
<p>SomeOtherValue <input data-bind="value: Test2.SomeOtherValue" /></p>
<p>Another <input data-bind="value: Test2.Another" /></p>
@* seeing if I can do it with p tags and see if they all update.*@
<p data-bind="foreach: Test3">
<strong data-bind="text: Test3Value"></strong>
</p>
@*took my 3rd view model that is in a collection and output all values as a textbox*@
<table>
<thead><tr>
<th>Test3</th>
</tr></thead>
<tbody data-bind="foreach: Test3">
<tr>
<td>
<strong data-bind="text: Test3Value"></strong>
<input type="text" data-bind="value: Test3Value"/>
</td>
</tr>
</tbody>
</table>
调节器
public ActionResult Index()
{
Test2 test2 = new Test2
{
Another = "test",
SomeOtherValue = "test2"
};
Test vm = new Test
{
FirstName = "Bob",
LastName = "N/A",
Test2 = test2,
};
for (int i = 0; i < 10; i++)
{
Test3 test3 = new Test3
{
Test3Value = i.ToString()
};
vm.Test3.Add(test3);
}
return View(vm);
}
我想我已经总结了所有的问题,如果我错过了什么,请告诉我( 如果你能在一个地方你所有的问题归纳起来将是很好 =))
注意。 与兼容性ko.editable
增加的插件
下载完整的代码
如何使用与knockout.js HTML辅助
这很简单:
@Html.TextBoxFor(model => model.CourseId, new { data_bind = "value: CourseId" })
哪里:
-
value: CourseId
表明您绑定的value
的财产input
与控制CourseId
从你的模型属性和脚本模型
其结果是:
<input data-bind="value: CourseId" data-val="true" data-val-number="The field CourseId must be a number." data-val-required="The CourseId field is required." id="CourseId" name="CourseId" type="text" value="12" />
为什么需要文档准备,使其工作(更多信息请参见第一次编辑)
为什么你需要使用我不明白,还没有ready
事件序列化模式,但它似乎仅仅是必需的 (不必担心它虽然)
我怎么做这样的事,如果我使用我的观点车型淘汰赛映射? 由于我没有因映射功能。
如果我理解正确的话,你需要一种新的方法追加到KO模型,很好,很容易合并模型
欲了解更多信息,在部分来自不同的来源- -Mapping
function viewModel() {
this.addStudent = function () {
alert("de");
};
};
$(function () {
var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
var mvcModel = ko.mapping.fromJSON(jsonModel);
var myViewModel = new viewModel();
var g = ko.mapping.fromJS(myViewModel, mvcModel);
ko.applyBindings(g);
});
关于警告你receiveing
警告1个条件编译被关闭 - > @ Html.Raw
你需要使用引号
与ko.editable插件兼容性
我认为这将是更为复杂,但事实证明,整合是很容易的,为了使你的模型编辑只需添加以下行:(记住,在这种情况下,我使用的是混合模式,从服务器在客户端加入扩展性和可编辑的简单的工作......这是伟大的):
ko.editable(g);
ko.applyBindings(g);
在这里,您只需要使用由插件添加的扩展您的绑定玩 ,比如我有一个按钮,开始编辑我的领域,如这和这个按钮我开始编辑过程:
this.editMode = function () {
this.isInEditMode(!this.isInEditMode());
this.beginEdit();
};
然后,我已经提交并取消用下面的代码按钮:
this.executeCommit = function () {
this.commit();
this.isInEditMode(false);
};
this.executeRollback = function () {
if (this.hasChanges()) {
if (confirm("Are you sure you want to discard the changes?")) {
this.rollback();
this.isInEditMode(false);
}
}
else {
this.rollback();
this.isInEditMode(false);
}
};
最后,我有一个字段,以指示场是否在编辑模式与否,这只是使能属性绑定。
this.isInEditMode = ko.observable(false);
关于您的问题阵
我可能有一些foreach循环或东西来获取数据了学生视图模型的集合。
然后,当我将提交表单,我会用jQuery和序列化阵列,并将其发送到将其绑定回视图模型控制器的操作方法。
你可以做同样的KO,在下面的例子中,我将创建以下的输出:
基本上在这里,你有两个列表,使用创建的Helpers
,并与KO绑定,他们有一个dblClick
事件绑定是发射时,从当前列表中删除选定的项目,并把它添加到其他列表中,当你邮寄到Controller
中,每个列表的内容被作为JSON数据和重新连接到服务器模型
掘金:
- Newtonsoft
- jQuery的
- knockoutjs
- Knockout.Mapping
外部脚本 。
控制器代码
[HttpGet]
public ActionResult Index()
{
var m = new CourseVM { CourseId = 12, CourseName = ".Net" };
m.StudentViewModels.Add(new StudentVm { ID = 545, Name = "Name from server", Lastname = "last name from server" });
return View(m);
}
[HttpPost]
public ActionResult Index(CourseVM model)
{
if (!string.IsNullOrWhiteSpace(model.StudentsSerialized))
{
model.StudentViewModels = JsonConvert.DeserializeObject<List<StudentVm>>(model.StudentsSerialized);
model.StudentsSerialized = string.Empty;
}
if (!string.IsNullOrWhiteSpace(model.SelectedStudentsSerialized))
{
model.SelectedStudents = JsonConvert.DeserializeObject<List<StudentVm>>(model.SelectedStudentsSerialized);
model.SelectedStudentsSerialized = string.Empty;
}
return View(model);
}
模型
public class CourseVM
{
public CourseVM()
{
this.StudentViewModels = new List<StudentVm>();
this.SelectedStudents = new List<StudentVm>();
}
public int CourseId { get; set; }
[Required(ErrorMessage = "Course name is required")]
[StringLength(100, ErrorMessage = "Course name cannot be this long.")]
public string CourseName { get; set; }
public List<StudentVm> StudentViewModels { get; set; }
public List<StudentVm> SelectedStudents { get; set; }
public string StudentsSerialized { get; set; }
public string SelectedStudentsSerialized { get; set; }
}
public class StudentVm
{
public int ID { get; set; }
public string Name { get; set; }
public string Lastname { get; set; }
}
CSHTML页
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>CourseVM</legend>
<div>
<div class="editor-label">
@Html.LabelFor(model => model.CourseId)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.CourseId, new { data_bind = "enable: isInEditMode, value: CourseId" })
@Html.ValidationMessageFor(model => model.CourseId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.CourseName)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.CourseName, new { data_bind = "enable: isInEditMode, value: CourseName" })
@Html.ValidationMessageFor(model => model.CourseName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.StudentViewModels);
</div>
<div class="editor-field">
@Html.ListBoxFor(
model => model.StudentViewModels,
new SelectList(this.Model.StudentViewModels, "ID", "Name"),
new
{
style = "width: 37%;",
data_bind = "enable: isInEditMode, options: StudentViewModels, optionsText: 'Name', value: leftStudentSelected, event: { dblclick: moveFromLeftToRight }"
}
)
@Html.ListBoxFor(
model => model.SelectedStudents,
new SelectList(this.Model.SelectedStudents, "ID", "Name"),
new
{
style = "width: 37%;",
data_bind = "enable: isInEditMode, options: SelectedStudents, optionsText: 'Name', value: rightStudentSelected, event: { dblclick: moveFromRightToLeft }"
}
)
</div>
@Html.HiddenFor(model => model.CourseId, new { data_bind="value: CourseId" })
@Html.HiddenFor(model => model.CourseName, new { data_bind="value: CourseName" })
@Html.HiddenFor(model => model.StudentsSerialized, new { data_bind = "value: StudentsSerialized" })
@Html.HiddenFor(model => model.SelectedStudentsSerialized, new { data_bind = "value: SelectedStudentsSerialized" })
</div>
<p>
<input type="submit" value="Save" data-bind="enable: !isInEditMode()" />
<button data-bind="enable: !isInEditMode(), click: editMode">Edit mode</button><br />
<div>
<button data-bind="enable: isInEditMode, click: addStudent">Add Student</button>
<button data-bind="enable: hasChanges, click: executeCommit">Commit</button>
<button data-bind="enable: isInEditMode, click: executeRollback">Cancel</button>
</div>
</p>
</fieldset>
}
脚本
<script src="@Url.Content("~/Scripts/jquery-1.7.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout-2.1.0.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout.mapping-latest.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ko.editables.js")" type="text/javascript"></script>
<script type="text/javascript">
var g = null;
function ViewModel() {
this.addStudent = function () {
this.StudentViewModels.push(new Student(25, "my name" + new Date(), "my last name"));
this.serializeLists();
};
this.serializeLists = function () {
this.StudentsSerialized(ko.toJSON(this.StudentViewModels));
this.SelectedStudentsSerialized(ko.toJSON(this.SelectedStudents));
};
this.leftStudentSelected = ko.observable();
this.rightStudentSelected = ko.observable();
this.moveFromLeftToRight = function () {
this.SelectedStudents.push(this.leftStudentSelected());
this.StudentViewModels.remove(this.leftStudentSelected());
this.serializeLists();
};
this.moveFromRightToLeft = function () {
this.StudentViewModels.push(this.rightStudentSelected());
this.SelectedStudents.remove(this.rightStudentSelected());
this.serializeLists();
};
this.isInEditMode = ko.observable(false);
this.executeCommit = function () {
this.commit();
this.isInEditMode(false);
};
this.executeRollback = function () {
if (this.hasChanges()) {
if (confirm("Are you sure you want to discard the changes?")) {
this.rollback();
this.isInEditMode(false);
}
}
else {
this.rollback();
this.isInEditMode(false);
}
};
this.editMode = function () {
this.isInEditMode(!this.isInEditMode());
this.beginEdit();
};
}
function Student(id, name, lastName) {
this.ID = id;
this.Name = name;
this.LastName = lastName;
}
$(function () {
var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
var mvcModel = ko.mapping.fromJSON(jsonModel);
var myViewModel = new ViewModel();
g = ko.mapping.fromJS(myViewModel, mvcModel);
g.StudentsSerialized(ko.toJSON(g.StudentViewModels));
g.SelectedStudentsSerialized(ko.toJSON(g.SelectedStudents));
ko.editable(g);
ko.applyBindings(g);
});
</script>
注:我只是说这几行:
@Html.HiddenFor(model => model.CourseId, new { data_bind="value: CourseId" })
@Html.HiddenFor(model => model.CourseName, new { data_bind="value: CourseName" })
因为当我提交表单我字段将被禁用,所以值不传输到服务器,这就是为什么我添加了几个隐藏字段这样的伎俩
你可以系列化你的ASP.NET MVC视图模型到一个JavaScript变量:
@model CourseVM
<script type="text/javascript">
var model = @Html.Raw(Json.Encode(Model));
// go ahead and use the model javascript variable to bind with ko
</script>
有很多的例子在淘汰赛的文档 ,你可以去。
为了获得额外的计算性能后,服务器映射时,将需要进一步加强对客户端您的ViewModels。
例如:
var viewModel = ko.mapping.fromJS(model);
viewModel.capitalizedName = ko.computed(function() {...}, viewModel);
所以,每当你从生JSON映射你需要重新计算的性能。
此外,该映射插件提供了增量更新,而不是每次来回走时重建它视图模型的能力(使用一个额外的参数fromJS
):
// Every time data is received from the server:
ko.mapping.fromJS(data, viewModel);
这对你的被映射只是性能的模型执行的增量数据更新。 您可以在阅读更多有关该映射文档
您在Darin的答案的评论提到FluentJSON包。 我的那个作者,但它的使用情况比ko.mapping更具体。 我一般只使用它,如果你的ViewModels是单向的(即服务器 - >客户端),然后数据被调回一些不同的格式(或者根本没有)。 或者,如果你的JavaScript视图模型需要在您的服务器模型实质上不同的格式。