2016-09-22 18 views
6

Piszę aplikację asp.net MVC i postanawiam wypróbować Knockout.js dla dynamicznego interfejsu użytkownika. To świetne ramy, które pomogły mi tak bardzo.Wysyłanie kolekcji z Knockout.js

Ale stanąłem w obliczu 2 problemów, których nie mogę rozwiązać i znaleźć żadnych przydatnych informacji na ten temat. Zacznę od kodu, aby pokazać, co mam, a następnie spróbuję wyjaśnić, co chcę osiągnąć.

C# ViewModel

Project ViewModel


ProjectServicesViewModel


ProjectPositionsViewModel

Moje HTML/Ra Zor i nokaut Moduł

var Project = function (project) { 
 
\t var self = this; 
 
\t self.Id = ko.observable(project ? project.Id : 0); 
 
\t self.CustumerCompany = ko.observable(project ? project.CustumerCompany : ""); 
 
\t self.CustomerRepresentative = ko.observable(project ? project.CustomerRepresentative : ""); 
 
\t self.ProjectTitle = ko.observable(project ? project.ProjectTitle : ""); 
 
\t self.WWSNumber = ko.observable(project ? project.WWSNumber : ""); 
 
\t self.AqStatus = ko.observable(project ? project.AqStatus : ""); 
 
\t self.Completed = ko.observable(project ? project.Completed : ""); 
 
\t self.StartDate = ko.observable(project ? project.StartDate : ""); 
 
\t self.EndDate = ko.observable(project ? project.EndDate : ""); 
 
\t self.ProjectLeader = ko.observable(project ? project.ProjectLeader : ""); 
 
\t self.Deputy = ko.observable(project ? project.Deputy : ""); 
 
\t self.SalesConsultant = ko.observable(project ? project.SalesConsultant : ""); 
 
\t self.Service = ko.observableArray(project ? project.Service : []); 
 
}; 
 

 
var ProjectService = function (projectService) { 
 
\t var self = this; 
 
\t self.Id = ko.observable(projectService ? projectService.Id : 0); 
 
\t self.Number = ko.observable(projectService ? projectService.Number : ""); 
 
\t self.Name = ko.observable(projectService ? projectService.Name : ""); 
 
\t self.Positions = ko.observableArray(projectService ? projectService.Positions : []); 
 
}; 
 

 
var ServicePosition = function (servicePosition) { 
 
\t var self = this; 
 
\t self.Id = ko.observable(servicePosition ? servicePosition.Id : 0); 
 
\t self.Number = ko.observable(servicePosition ? servicePosition.Number : ""); 
 
\t self.Name = ko.observable(servicePosition ? servicePosition.Name : ""); 
 
\t self.PerformanceGroup = ko.observable(servicePosition ? servicePosition.PerformanceGroup : ""); 
 
\t self.PerformanceGroupPrice = ko.observable(servicePosition ? servicePosition.PerformanceGroupPrice : ""); 
 
\t self.Remarks = ko.observable(servicePosition ? servicePosition.Remarks : ""); 
 
}; 
 

 
var ProjectCollection = function() { 
 
\t var self = this; 
 

 
\t self.project = ko.observable(new Project()); 
 
\t self.projectServices = ko.observableArray([new ServicePosition()]); 
 
\t self.servicePositions = ko.observableArray([new ServicePosition()]); 
 

 
\t self.addService = function() { 
 
\t \t self.projectServices.push(new ProjectService()); 
 
\t \t console.log(self.projectServices); 
 
\t }; 
 
\t self.removeService = function (projectService) { 
 
\t \t self.projectServices.remove(projectService); 
 
\t }; 
 

 

 

 
\t self.saveProject = function() { 
 
\t \t self.project().Service = self.projectServices; 
 
\t \t console.log(self.projectServices); 
 
\t \t console.log(self.project()); 
 

 
\t \t var token = $('[name=__RequestVerificationToken]').val(); 
 

 
\t \t $.ajax({ 
 
\t \t \t type: "POST", 
 
\t \t \t url: "/LeistungManager/CreateProject", 
 
\t \t \t data: { __RequestVerificationToken: token, model: ko.toJS(self.project()) }, 
 
\t \t \t dataType: "json", 
 
\t \t \t cache: false, 
 
\t \t \t async: true, 
 
\t \t \t success: function (response) { 
 

 
\t \t \t }, 
 
\t \t \t complete: function (response) { 
 
\t \t \t \t console.log(response); 
 
\t \t \t } 
 
\t \t }); 
 
\t }; 
 

 
}; 
 
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>

Moja Wynik wygląda

Design

Problem nr 1

W. Czy wprowadzam wszystkie informacje i dodam kilka elementów usług projektowych do kontrolera odbierającego, ale właściwości usługi są puste i nie mogę się domyślić, dlaczego? Co robię źle?

Result

Problem Nr 2

Następny do projektu panel serwisowy (zobaczyć projekt ekranu) zbuduję inny niemal tego samego panelu, ale w tym oknie samo Dodaj do listy funkcjonalności powinny zależeć na którą pozycję wybieram w panelu usług projektu. Na przykład:

Po wybraniu pierwszego elementu w panelu Usługi projektu po prawej stronie powinien pojawić się panel z przyciskiem DODAJ, aby umieścić przedmiot na innej liście. Po umieszczeniu informacji w jednym elemencie mogę wybrać inny i umieścić go, a panel powinien zaktualizować w oparciu o wybór Usługi projektu. Nie mogę znaleźć nigdzie przykładu, artykułu lub samouczka, jak osiągnąć ten rodzaj wyniku. Wszelka pomoc z pomocą!

+0

Sterownik musi wiedzieć, jak przeanalizować żądanie. możesz użyć 'contentType: 'application/json;' 'w twojej opcji ajax. – janmvtrinidad

+0

To zna i bez tego –

+0

Naprawdę trzeba ustawić contentType: "application/json" i stringify swoje dane, więc 'dane: JSON.stringify ({__RequestVerificationToken: token, model: ko.toJS (self.project()) }) zobacz http://stackoverflow.com/questions/14591437/deserialising-json-into-nested-view-model-in-controller. 'dataType' jest ** only ** istotne, gdy otrzymujesz dane z serwera. Podczas wysyłania danych należy ustawić "contentType" – nemesv

Odpowiedz

3

Po pewnym czasie czytania dokumentacji udaje mi się rozwiązać mój problem. Więc tutaj działa kod JS HTML jest taka sama jak w moim pytaniu:

/// <reference path="../jquery-3.1.0.intellisense.js" /> 
 

 

 
\t var ProjectModel = function (project) { 
 
\t \t var self = this; 
 
\t \t self.Id = ko.observable(project ? project.Id : 0); 
 

 
\t \t self.CustumerCompany = ko.observable(project ? project.CustumerCompany : ""); 
 

 
\t \t self.CustomerRepresentative = ko.observable(project ? project.CustomerRepresentative : ""); 
 

 
\t \t self.ProjectTitle = ko.observable(project ? project.ProjectTitle : ""); 
 

 
\t \t self.WWSNumber = ko.observable(project ? project.WWSNumber : ""); 
 

 
\t \t self.AqStatus = ko.observable(project ? project.AqStatus : ""); 
 

 
\t \t self.Completed = ko.observable(project ? project.Completed : ""); 
 

 
\t \t self.StartDate = ko.observable(project ? project.StartDate : ""); 
 

 
\t \t self.EndDate = ko.observable(project ? project.EndDate : ""); 
 

 
\t \t self.ProjectLeader = ko.observable(project ? project.ProjectLeader : ""); 
 

 
\t \t self.Deputy = ko.observable(project ? project.Deputy : ""); 
 

 
\t \t self.SalesConsultant = ko.observable(project ? project.SalesConsultant : ""); 
 

 
\t \t self.Service = ko.observableArray(project ? project.Service : []); 
 

 
\t }; 
 

 

 
\t // #endregion 
 

 
\t // #region Project Service Model 
 

 
\t var ProjectServiceModel = function (projectService) { 
 
\t \t var self = this; 
 
\t \t self.Id = ko.observable(projectService ? projectService.Id : 0); 
 

 
\t \t self.Number = ko.observable(projectService ? projectService.Number : ""); 
 

 
\t \t self.Name = ko.observable(projectService ? projectService.Name : ""); 
 

 
\t \t self.Positions = ko.observableArray(projectService ? projectService.Positions : []); 
 

 
\t \t self.isEditing = ko.observable(true); 
 

 
\t \t self.isActive = ko.observable(false); 
 

 
\t \t self.countSelf = ko.computed(function() { 
 
\t \t \t if (self.Positions().length > 0) { 
 
\t \t \t \t return true; 
 
\t \t \t } 
 
\t \t \t else { 
 
\t \t \t \t return false; 
 
\t \t \t } 
 

 
\t \t }, 
 
\t self); 
 

 
\t }; 
 

 

 
\t // #endregion 
 

 
\t // #region Position Model 
 
\t var ServicePositionModel = function (servicePosition) { 
 
\t \t var self = this; 
 
\t \t self.Id = ko.observable(servicePosition ? servicePosition.Id : 0); 
 

 
\t \t self.Number = ko.observable(servicePosition ? servicePosition.Number : ""); 
 

 
\t \t self.Name = ko.observable(servicePosition ? servicePosition.Name : ""); 
 

 
\t \t self.PerformanceGroup = ko.observable(servicePosition ? servicePosition.PerformanceGroup : ""); 
 

 
\t \t self.PerformanceGroupPrice = ko.observable(servicePosition ? servicePosition.PerformanceGroupPrice : ""); 
 

 
\t \t self.Remarks = ko.observable(servicePosition ? servicePosition.Remarks : ""); 
 

 
\t \t self.isEditing = ko.observable(servicePosition ? servicePosition.isEditing : false); 
 

 
\t \t self.isActive = ko.observable(false); 
 

 
\t }; 
 

 
\t // #endregion 
 

 

 
\t var ProjectViewModel = function() { 
 
\t \t var self = this; 
 

 
\t \t self.project = ko.observable(new ProjectModel()); 
 

 
\t \t self.projectServices = ko.observableArray([]); 
 

 
\t \t // #region InitData 
 

 
\t \t 
 

 
\t \t self.selectedPerformanceGroup = ko.observableArray([]); 
 
\t \t self.AqStatusTypeData = ko.observableArray([]); 
 
\t \t self.PerformanceGroupTypeData = ko.observableArray([]); 
 
\t \t $.ajax({ 
 
\t \t \t url: "/LeistungManager/InitializeData", 
 
\t \t \t dataType: "json", 
 
\t \t \t success: function (json) { 
 
\t \t \t \t self.AqStatusTypeData(json.AqStatusType); 
 
\t \t \t \t self.PerformanceGroupTypeData(json.PerformanceGroupType); 
 
\t \t \t } 
 
\t \t }); 
 

 

 
\t \t self.testOptions = function() { 
 
\t \t \t 
 
\t \t \t self.selectedPerformanceGroup; 
 
\t \t \t debugger; 
 
\t \t } 
 

 
\t \t // #endregion 
 

 
\t \t // #region Service Functions 
 
\t \t self.addService = function() { 
 
\t \t \t var object = new Object(); 
 

 
\t \t \t object.isEditing = true; 
 
\t \t \t self.projectServices.push(new ProjectServiceModel(object)); 
 

 
\t \t \t self.isServiceSelected(false); 
 

 
\t \t }; 
 

 

 
\t \t self.saveService = function (projectService) { 
 
\t \t \t projectService.isEditing(false); 
 

 
\t \t }; 
 

 
\t \t self.editService = function (projectService) { 
 
\t \t \t projectService.isEditing(true); 
 

 
\t \t }; 
 

 
\t \t self.removeService = function (projectService) { 
 
\t \t \t self.projectServices.remove(projectService); 
 

 
\t \t }; 
 

 

 
\t \t self.isServiceSelected = ko.observable(false); 
 

 
\t \t self.selectedServiceData = ko.observable(new Object()); 
 

 
\t \t self.selectService = function (serviceRowData) { 
 
\t \t \t if (!serviceRowData.isEditing()) { 
 
\t \t \t \t self.isServiceSelected(true); 
 

 
\t \t \t \t serviceRowData.isActive(true); 
 

 
\t \t \t \t self.selectedServiceData(serviceRowData); 
 

 
\t \t \t } 
 

 
\t \t }; 
 

 
\t \t // #endregion 
 

 

 
\t \t // #region Position Functions 
 
\t \t self.addPosition = function() { 
 
\t \t \t var object = new Object(); 
 

 
\t \t \t object.isEditing = true; 
 
\t \t \t self.selectedServiceData().Positions.push(new ServicePositionModel(object)); 
 

 
\t \t }; 
 

 

 
\t \t self.savePosition = function (servicePosition) { 
 
\t \t \t servicePosition.isEditing(false); 
 

 
\t \t }; 
 

 
\t \t self.editPosition = function (servicePosition) { 
 
\t \t \t servicePosition.isEditing(true); 
 

 
\t \t }; 
 

 
\t \t self.removePosition = function (servicePosition) { 
 
\t \t \t self.selectedServiceData().Positions.remove(servicePosition); 
 

 
\t \t }; 
 

 

 
\t \t self.isPositionSelected = ko.observable(false); 
 

 
\t \t self.selectedPositionData = ko.observable(ServicePositionModel(new Object())); 
 

 
\t \t self.selectPosition = function (positionRowData) { 
 
\t \t \t if (!positionRowData.isEditing()) { 
 
\t \t \t \t self.isPositionSelected(true); 
 

 
\t \t \t \t positionRowData.isActive(true); 
 

 
\t \t \t \t self.selectedPositionData(positionRowData); 
 

 

 
\t \t \t } 
 

 
\t \t }; 
 

 
\t \t // #endregion 
 

 
\t \t self.saveProject = function() { 
 
\t \t \t self.project().Service = self.projectServices; 
 
\t \t \t self.project().Service().Positions = self.servicePositions; 
 

 
\t \t \t var token = $('[name=__RequestVerificationToken]').val(); 
 

 

 
\t \t \t $.ajax({ 
 
\t \t \t \t type: "POST", 
 
\t \t \t \t url: "/LeistungManager/CreateProject", 
 
\t \t \t \t data: { __RequestVerificationToken: token, model: ko.toJS(self.project()) }, 
 

 
\t \t \t \t dataType: "json", 
 
\t \t \t \t cache: false, 
 
\t \t \t \t async: true, 
 
\t \t \t \t success: function (response) { 
 

 
\t \t \t \t }, 
 

 
\t \t \t \t complete: function (response) { 
 
\t \t \t \t \t console.log(response); 
 

 
\t \t \t \t } 
 

 
\t \t \t }); 
 

 
\t \t }; 
 

 

 
\t }; 
 

 
ko.applyBindings(new ProjectViewModel());

Magia była z tworzeniem selectedServiceData zmienną do zaobserwowania i przekazać go do selectPosition funkcję na kliknięcia przycisku . Potem mogłem pracować z wybranymi macierzami i danymi przedmiotów.

Jeśli ktoś potrzebuje bardziej szczegółowego wyjaśnienia lub pomocy przy kodzie - daj mi znać.

2

Dla Państwa:

Problem 1 można dodać contentType: 'application/json;' w ajax żądanie kontrolera, aby wiedzieć, jak analizować żądania.

Problem 2 patrz na przykład fiddle na przykład swojego kodu. Możesz sprawdzić to documentation, aby wiedzieć, gdzie użyć innego kontekstu powiązania.

+0

Jeśli chodzi o typ zawartości - nie stanowi to problemu. Ponieważ kontroler otrzymuje informacje o elementach, które nie są obserwowalneArray w Vm i już istnieje dataType. Dotyczące problemu nr. 2 Czytałem już tę dokumentację, potrzebuję przykładu mojego celu –