如何在knockoutjs中使用嵌套viewmodels进行动态增删改查
How to perform dynamic add, delete and save with nested viewmodels in knockoutjs
在 MVC 中,您可以拥有以下视图模型:
public class MyCVViewModel
{
[Required]
[StringLength(100, ErrorMessage = "Resume Title cannot exceed 100 characters.")]
[Display(Name = "Resume Title")]
public string ResumeTitle { get; set; }
[Required]
[StringLength(1000, ErrorMessage = "Personal Statment cannot exceed 1000 characters.")]
[Display(Name = "Personal Statement")]
public string Statement { get; set; }
public List<MyCompanyViewModel> Companies { get; set; }
}
public class MyCompanyViewModel
{
[Required]
[StringLength(100, ErrorMessage = "Company Name cannot exceed 100 characters.")]
[Display(Name = "Company Name")]
public string CompanyName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "Job Title cannot exceed 100 characters.")]
[Display(Name = "Job Title")]
public string JobTitle { get; set; }
[Required]
[DataType(DataType.Date)]
[Display(Name = "Start Date")]
public DateTime JobStartDate { get; set; }
[Required]
[DataType(DataType.Date)]
[Display(Name = "End Date")]
public DateTime JobEndDate { get; set; }
[Required]
[StringLength(1000, ErrorMessage = "Job Description cannot exceed 1000 characters.")]
[Display(Name = "Job Description")]
public string JobDescription { get; set; }
}
MyCVViewModel 有一个 MyCompanyViewModels 列表,这非常简单。
我开始学习 knockoutjs 并尝试在 knockoutjs 中复制相同的视图模型。
这是我到目前为止尝试过的方法:
//company viewmodel
function Company(data) {
this.name = ko.observable(data.name);
//other stuff
}
//cv view model
function CVViewModel() {
var self = this;
self.title = ko.oberservable();
self.statement = ko.oberservalbe();
//list of company view model
self.companies = ko.observableArray();
//add company
self.addCompany = function () {
self.companies.push({
name: ""
});
};
//remove company
self.removeCompany = function (company) {
self.companies.remove(company);
};
//populate with json
$.getJSON("/Class/FillCompany", function (allData) {
var mappedTasks = $.map(allData, function (item) { return new Company(item) });
self.companies(mappedTasks);
});
};
// Activate knockout binding
ko.applyBindings(new CVViewModel());
添加和删除工作正常,但我不确定如何将整个 cv viewmodel 和 post 保存到 asp.net mvc 中的控制器。
大多数在线教程 post 子视图模型(在我的公司列表中)和 post 它到服务器而不是父视图模型(在我的示例中是 cvviewmdoel)。
所以在我看来我只能post服务器的公司:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<textarea name="companies" data-bind="value: ko.toJSON(companies)"></textarea>
<button type="submit">Save</button>
}
在我的控制器中,我希望有一个公司列表:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index([FromJson] IEnumerable<Company> companies)
{
//save to database etc..
}
如何 post 整个父视图模型,以便我的控制器看起来更像:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(MyCVViewModel cv)
{
//save to database etc..
}
其中 MyCVViewModel 已包含公司列表。
只需在客户端上进行一些编程,您就可以完成这项工作。
首先,您可能想为自己节省一些时间,除非您需要与每家公司进行一些使用 ko.mapping
无法通过订阅者处理的事情
ko.mapping.fromJS(allData, {} self.companies)
此外,在添加新公司时,您需要保持其可观察性,因此请使用:
self.companies.push(new Company(name));
您可以将整个模型 header 和 children 作为 json object 发送以匹配您的服务器端 object.
因此将您的视图模型更改为以下内容:
function viewModel()
{
var self = this;
self.title = ko.oberservable();
self.statement = ko.oberservalbe();
//list of company view model
self.companies = ko.observableArray();
//add company
self.addCompany = function () {
self.companies.push(new Company(name));
};
//remove company
self.removeCompany = function (company) {
self.companies.remove(company);
};
//populate with json
$.getJSON("/Class/FillCompany", function (allData) {
ko.mapping.fromJS(allData, {} self.companies)
});
//save
saveModel = function(){
var data = ko.mapping.toJS(self);
$ajax({
url: 'Class/SaveCompany',
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: data,
success: function (data, textStatus, jqXhr) {
//do success stuff here.
}
}
然后在您提交时,将您的点击事件绑定到视图模型保存事件,它会发送一个 parent 模型,其中所有 children 作为单个表单 post。
希望对您有所帮助。
在 MVC 中,您可以拥有以下视图模型:
public class MyCVViewModel
{
[Required]
[StringLength(100, ErrorMessage = "Resume Title cannot exceed 100 characters.")]
[Display(Name = "Resume Title")]
public string ResumeTitle { get; set; }
[Required]
[StringLength(1000, ErrorMessage = "Personal Statment cannot exceed 1000 characters.")]
[Display(Name = "Personal Statement")]
public string Statement { get; set; }
public List<MyCompanyViewModel> Companies { get; set; }
}
public class MyCompanyViewModel
{
[Required]
[StringLength(100, ErrorMessage = "Company Name cannot exceed 100 characters.")]
[Display(Name = "Company Name")]
public string CompanyName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "Job Title cannot exceed 100 characters.")]
[Display(Name = "Job Title")]
public string JobTitle { get; set; }
[Required]
[DataType(DataType.Date)]
[Display(Name = "Start Date")]
public DateTime JobStartDate { get; set; }
[Required]
[DataType(DataType.Date)]
[Display(Name = "End Date")]
public DateTime JobEndDate { get; set; }
[Required]
[StringLength(1000, ErrorMessage = "Job Description cannot exceed 1000 characters.")]
[Display(Name = "Job Description")]
public string JobDescription { get; set; }
}
MyCVViewModel 有一个 MyCompanyViewModels 列表,这非常简单。
我开始学习 knockoutjs 并尝试在 knockoutjs 中复制相同的视图模型。
这是我到目前为止尝试过的方法:
//company viewmodel
function Company(data) {
this.name = ko.observable(data.name);
//other stuff
}
//cv view model
function CVViewModel() {
var self = this;
self.title = ko.oberservable();
self.statement = ko.oberservalbe();
//list of company view model
self.companies = ko.observableArray();
//add company
self.addCompany = function () {
self.companies.push({
name: ""
});
};
//remove company
self.removeCompany = function (company) {
self.companies.remove(company);
};
//populate with json
$.getJSON("/Class/FillCompany", function (allData) {
var mappedTasks = $.map(allData, function (item) { return new Company(item) });
self.companies(mappedTasks);
});
};
// Activate knockout binding
ko.applyBindings(new CVViewModel());
添加和删除工作正常,但我不确定如何将整个 cv viewmodel 和 post 保存到 asp.net mvc 中的控制器。
大多数在线教程 post 子视图模型(在我的公司列表中)和 post 它到服务器而不是父视图模型(在我的示例中是 cvviewmdoel)。
所以在我看来我只能post服务器的公司:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<textarea name="companies" data-bind="value: ko.toJSON(companies)"></textarea>
<button type="submit">Save</button>
}
在我的控制器中,我希望有一个公司列表:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index([FromJson] IEnumerable<Company> companies)
{
//save to database etc..
}
如何 post 整个父视图模型,以便我的控制器看起来更像:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(MyCVViewModel cv)
{
//save to database etc..
}
其中 MyCVViewModel 已包含公司列表。
只需在客户端上进行一些编程,您就可以完成这项工作。
首先,您可能想为自己节省一些时间,除非您需要与每家公司进行一些使用 ko.mapping
无法通过订阅者处理的事情ko.mapping.fromJS(allData, {} self.companies)
此外,在添加新公司时,您需要保持其可观察性,因此请使用:
self.companies.push(new Company(name));
您可以将整个模型 header 和 children 作为 json object 发送以匹配您的服务器端 object.
因此将您的视图模型更改为以下内容:
function viewModel()
{
var self = this;
self.title = ko.oberservable();
self.statement = ko.oberservalbe();
//list of company view model
self.companies = ko.observableArray();
//add company
self.addCompany = function () {
self.companies.push(new Company(name));
};
//remove company
self.removeCompany = function (company) {
self.companies.remove(company);
};
//populate with json
$.getJSON("/Class/FillCompany", function (allData) {
ko.mapping.fromJS(allData, {} self.companies)
});
//save
saveModel = function(){
var data = ko.mapping.toJS(self);
$ajax({
url: 'Class/SaveCompany',
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: data,
success: function (data, textStatus, jqXhr) {
//do success stuff here.
}
}
然后在您提交时,将您的点击事件绑定到视图模型保存事件,它会发送一个 parent 模型,其中所有 children 作为单个表单 post。
希望对您有所帮助。