简体   繁体   English

使用Knockout.js发布集合

[英]Posting Collection with Knockout.js

I'm writing an asp.net MVC application and decide to try Knockout.js for dynamic UI stuff. 我正在编写一个asp.net MVC应用程序并决定尝试使用Knockout.js来获取动态UI内容。 It's a great framework it helped me so much so far. 这是一个很棒的框架,它迄今为止帮助了我很多。

But I faced 2 problems that I can't solve and find any useful information on that. 但我遇到了两个我无法解决的问题,并找到了有用的信息。 I'll start with code to show you what I have and then I shall try to explain what I want to achieve. 我将从代码开始向您展示我所拥有的内容然后我将尝试解释我想要实现的目标。

C# ViewModel C#ViewModel

项目ViewModel


ProjectServicesViewModel


ProjectPositionsViewModel

My HTML/Razor and knockout Module 我的HTML / Razor和淘汰模块

 var Project = function (project) { var self = this; self.Id = ko.observable(project ? project.Id : 0); self.CustumerCompany = ko.observable(project ? project.CustumerCompany : ""); self.CustomerRepresentative = ko.observable(project ? project.CustomerRepresentative : ""); self.ProjectTitle = ko.observable(project ? project.ProjectTitle : ""); self.WWSNumber = ko.observable(project ? project.WWSNumber : ""); self.AqStatus = ko.observable(project ? project.AqStatus : ""); self.Completed = ko.observable(project ? project.Completed : ""); self.StartDate = ko.observable(project ? project.StartDate : ""); self.EndDate = ko.observable(project ? project.EndDate : ""); self.ProjectLeader = ko.observable(project ? project.ProjectLeader : ""); self.Deputy = ko.observable(project ? project.Deputy : ""); self.SalesConsultant = ko.observable(project ? project.SalesConsultant : ""); self.Service = ko.observableArray(project ? project.Service : []); }; var ProjectService = function (projectService) { var self = this; self.Id = ko.observable(projectService ? projectService.Id : 0); self.Number = ko.observable(projectService ? projectService.Number : ""); self.Name = ko.observable(projectService ? projectService.Name : ""); self.Positions = ko.observableArray(projectService ? projectService.Positions : []); }; var ServicePosition = function (servicePosition) { var self = this; self.Id = ko.observable(servicePosition ? servicePosition.Id : 0); self.Number = ko.observable(servicePosition ? servicePosition.Number : ""); self.Name = ko.observable(servicePosition ? servicePosition.Name : ""); self.PerformanceGroup = ko.observable(servicePosition ? servicePosition.PerformanceGroup : ""); self.PerformanceGroupPrice = ko.observable(servicePosition ? servicePosition.PerformanceGroupPrice : ""); self.Remarks = ko.observable(servicePosition ? servicePosition.Remarks : ""); }; var ProjectCollection = function () { var self = this; self.project = ko.observable(new Project()); self.projectServices = ko.observableArray([new ServicePosition()]); self.servicePositions = ko.observableArray([new ServicePosition()]); self.addService = function () { self.projectServices.push(new ProjectService()); console.log(self.projectServices); }; self.removeService = function (projectService) { self.projectServices.remove(projectService); }; self.saveProject = function () { self.project().Service = self.projectServices; console.log(self.projectServices); console.log(self.project()); var token = $('[name=__RequestVerificationToken]').val(); $.ajax({ type: "POST", url: "/LeistungManager/CreateProject", data: { __RequestVerificationToken: token, model: ko.toJS(self.project()) }, dataType: "json", cache: false, async: true, success: function (response) { }, complete: function (response) { console.log(response); } }); }; }; ko.applyBindings(new ProjectCollection()); 
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <div class="row"> <div class="col-md-6"> <div class="widget"> <div class="widget-heading"> <h3 class="widget-title">Project Services</h3> <div> <form class="form-inline"> <p> <div class="form-group"> <label>WWS-Number</label> <input class="form-control" placeholder="Number" data-bind="value: $root.Number" /> <label>WWS-Number</label> <input class="form-control" placeholder="Name" data-bind="value: $root.Name" /> <button class="btn btn-primary" data-bind="click: addService">Add</button> </div> </p> </form> </div> </div> <div class="widget-body"> <table data-bind="visible: projectServices().length > 0 " class="table"> <thead> <tr> <th> Number </th> <th> Service Name </th> <th> </th> </tr> </thead> <tbody data-bind="foreach: projectServices"> <tr> <td data-bind="text: $parent.Number"></td> <td data-bind="text: $parent.Name"></td> <td> <button class="btn btn-success">Edit</button> <button class="btn btn-danger" data-bind="click: $root.removeService">Delete</button> </td> </tr> </tbody> </table> </div> </div> </div> </div> 

My Result looks like 我的结果看起来像

设计

Problem Nr 1 问题Nr 1

When I enter all information and adding few project services item's my controller receive model but Service's properties are empty and I can't figure out why? 当我输入所有信息并添加一些项目服务项时,我的控制器接收模型但服务的属性是空的,我无法弄清楚为什么? What I'm doing wrong? 我做错了什么?

结果

Problem Nr 2 问题Nr 2

Next to Project Service panel ( see design screenshot ) I will build another almost the same panel but in that window the same Add To List functionality should depend on which Item I select in Project Service Panel. 在Project Service面板旁边( 参见设计截图 )我将构建另一个几乎相同的面板,但在该窗口中,相同的Add To List功能应取决于我在Project Service Panel中选择的项目。 For example: 例如:

If I selected first item in Project Service panel on the right should appear panel with ADD button so I can put item to another list. 如果我在右侧的“项目服务”面板中选择了第一项,则应显示带有“添加”按钮的面板,以便我可以将项目放入另一个列表。 After I put information to one item I can selected another and put there and panel should update based on Project Service selection. 在我将信息放到一个项目后,我可以选择另一个并放在那里,面板应根据项目服务选择进行更新。 I can't find anywhere example, article or tutorial how to achieve this kind of result. 我无法在任何地方找到示例,文章或教程如何实现这种结果。 Any kind of help with be helpful! 任何有用的帮助都有帮助!

For your: 为您:

Problem 1 you can add contentType: 'application/json;' 问题1你可以添加contentType: 'application/json;' in your ajax request for the controller to know how to parse your request. 在您的ajax请求中,控制器知道如何解析您的请求。

Problem 2 see this fiddle for example of your code. 问题2看到这个小提琴 ,例如你的代码。 You can check this documentation in order for you to know where to use different binding context. 您可以查看此文档 ,以便了解在何处使用不同的绑定上下文。

After some time reading documentation I manage to solve my problem. 经过一段时间阅读文档后,我设法解决了我的问题。 So here is working JS code HTML is the same as in my question: 所以这里工作JS代码HTML与我的问题相同:

 /// <reference path="../jquery-3.1.0.intellisense.js" /> var ProjectModel = function (project) { var self = this; self.Id = ko.observable(project ? project.Id : 0); self.CustumerCompany = ko.observable(project ? project.CustumerCompany : ""); self.CustomerRepresentative = ko.observable(project ? project.CustomerRepresentative : ""); self.ProjectTitle = ko.observable(project ? project.ProjectTitle : ""); self.WWSNumber = ko.observable(project ? project.WWSNumber : ""); self.AqStatus = ko.observable(project ? project.AqStatus : ""); self.Completed = ko.observable(project ? project.Completed : ""); self.StartDate = ko.observable(project ? project.StartDate : ""); self.EndDate = ko.observable(project ? project.EndDate : ""); self.ProjectLeader = ko.observable(project ? project.ProjectLeader : ""); self.Deputy = ko.observable(project ? project.Deputy : ""); self.SalesConsultant = ko.observable(project ? project.SalesConsultant : ""); self.Service = ko.observableArray(project ? project.Service : []); }; // #endregion // #region Project Service Model var ProjectServiceModel = function (projectService) { var self = this; self.Id = ko.observable(projectService ? projectService.Id : 0); self.Number = ko.observable(projectService ? projectService.Number : ""); self.Name = ko.observable(projectService ? projectService.Name : ""); self.Positions = ko.observableArray(projectService ? projectService.Positions : []); self.isEditing = ko.observable(true); self.isActive = ko.observable(false); self.countSelf = ko.computed(function () { if (self.Positions().length > 0) { return true; } else { return false; } }, self); }; // #endregion // #region Position Model var ServicePositionModel = function (servicePosition) { var self = this; self.Id = ko.observable(servicePosition ? servicePosition.Id : 0); self.Number = ko.observable(servicePosition ? servicePosition.Number : ""); self.Name = ko.observable(servicePosition ? servicePosition.Name : ""); self.PerformanceGroup = ko.observable(servicePosition ? servicePosition.PerformanceGroup : ""); self.PerformanceGroupPrice = ko.observable(servicePosition ? servicePosition.PerformanceGroupPrice : ""); self.Remarks = ko.observable(servicePosition ? servicePosition.Remarks : ""); self.isEditing = ko.observable(servicePosition ? servicePosition.isEditing : false); self.isActive = ko.observable(false); }; // #endregion var ProjectViewModel = function () { var self = this; self.project = ko.observable(new ProjectModel()); self.projectServices = ko.observableArray([]); // #region InitData self.selectedPerformanceGroup = ko.observableArray([]); self.AqStatusTypeData = ko.observableArray([]); self.PerformanceGroupTypeData = ko.observableArray([]); $.ajax({ url: "/LeistungManager/InitializeData", dataType: "json", success: function (json) { self.AqStatusTypeData(json.AqStatusType); self.PerformanceGroupTypeData(json.PerformanceGroupType); } }); self.testOptions = function () { self.selectedPerformanceGroup; debugger; } // #endregion // #region Service Functions self.addService = function () { var object = new Object(); object.isEditing = true; self.projectServices.push(new ProjectServiceModel(object)); self.isServiceSelected(false); }; self.saveService = function (projectService) { projectService.isEditing(false); }; self.editService = function (projectService) { projectService.isEditing(true); }; self.removeService = function (projectService) { self.projectServices.remove(projectService); }; self.isServiceSelected = ko.observable(false); self.selectedServiceData = ko.observable(new Object()); self.selectService = function (serviceRowData) { if (!serviceRowData.isEditing()) { self.isServiceSelected(true); serviceRowData.isActive(true); self.selectedServiceData(serviceRowData); } }; // #endregion // #region Position Functions self.addPosition = function () { var object = new Object(); object.isEditing = true; self.selectedServiceData().Positions.push(new ServicePositionModel(object)); }; self.savePosition = function (servicePosition) { servicePosition.isEditing(false); }; self.editPosition = function (servicePosition) { servicePosition.isEditing(true); }; self.removePosition = function (servicePosition) { self.selectedServiceData().Positions.remove(servicePosition); }; self.isPositionSelected = ko.observable(false); self.selectedPositionData = ko.observable(ServicePositionModel(new Object())); self.selectPosition = function (positionRowData) { if (!positionRowData.isEditing()) { self.isPositionSelected(true); positionRowData.isActive(true); self.selectedPositionData(positionRowData); } }; // #endregion self.saveProject = function () { self.project().Service = self.projectServices; self.project().Service().Positions = self.servicePositions; var token = $('[name=__RequestVerificationToken]').val(); $.ajax({ type: "POST", url: "/LeistungManager/CreateProject", data: { __RequestVerificationToken: token, model: ko.toJS(self.project()) }, dataType: "json", cache: false, async: true, success: function (response) { }, complete: function (response) { console.log(response); } }); }; }; ko.applyBindings(new ProjectViewModel()); 

The magic was with creating selectedServiceData observable variable and pass it to selectPosition function on button click. 神奇的是创建selectedServiceData可观察变量并在按钮点击时将其传递给selectPosition函数。 After that I could work with selected Item arrays and data. 之后我可以使用选定的Item数组和数据。

If anybody needs more detailed explanation or help with code - let me know. 如果有人需要更详细的解释或帮助代码 - 请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM