Note that there are some explanatory texts on larger screens.

plurals
  1. POKnockout Mapping Observable Array MVC
    primarykey
    data
    text
    <p>Hi I have looked around online for hours trying to solve this but I couldn't find a solution.</p> <p>I am building the solution using ASP.NET MVC and Knockout. The controller returns the options for the user to select from to the view which converts it into JSON and uses the mapping plugin to map it to a knockout View Model. It populates correctly because when I do this: ko.toJSON($data) to test it, the correct data is returned but the view won't update the list when an item is added to it.</p> <p>My guess is that the properties aren't observables but I'm not sure how to fix that.</p> <p>This is an example of the JSON Returned:</p> <p>[{"Key":1,"Value":"company"}]</p> <p>This is my javascript:</p> <pre><code>function ProjectWorkedOn() { var self = this; self.client = ko.observable(); self.job = ko.observable(); self.project = ko.observable(); self.workType = ko.observable(); } function createTimesheetViewModel() { var self = this; //list of options self.UserClients = ko.observableArray(); self.UserProjects = ko.observableArray(); self.UserJobs = ko.observableArray(); self.UserWorkTypes = ko.observableArray(); //keep track of selected options self.selectedClient = ko.observable(); self.selectedProject = ko.observable(); self.selectedJob = ko.observable(); self.selectedWorkType = ko.observable(); //list to add choices in self.ListProjectsWorkedOn = ko.observableArray(); self.addProjectWorkedOn = function () { var project = new ProjectWorkedOn(); project.client = self.selectedClient; project.job = self.selectedJob; project.project = self.selectedProject; project.workType = self.selectedWorkType; self.ListProjectsWorkedOn.push(project) } self.removeProjectWorkedOn = function (projectWorkedOn) { self.ListProjectsWorkedOn.remove(projectWorkedOn) } } $(function () { var CreateTimesheetViewModel = new createTimesheetViewModel(); CreateTimesheetViewModel.UserClients = ko.mapping.fromJSON('@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.UserClients))'); CreateTimesheetViewModel.UserProjects = ko.mapping.fromJSON('@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.UserProjects))'); CreateTimesheetViewModel.UserJobs = ko.mapping.fromJSON('@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.UserJobs))'); CreateTimesheetViewModel.UserWorkTypes = ko.mapping.fromJSON('@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.UserWorkTypes))'); ko.applyBindings(CreateTimesheetViewModel, document.getElementById("CreateTimesheet")); }); </code></pre> <p>This is the part of the view that adds items to the list: </p> <pre><code>&lt;table&gt; &lt;tr&gt; &lt;td&gt; Projects Worked On: &lt;/td&gt; &lt;td&gt; Client: &lt;select data-bind="options: UserClients, optionsText: 'Value', value: selectedClient"&gt;&lt;/select&gt; &lt;/td&gt; &lt;td&gt; Project: &lt;select data-bind="options: UserProjects, optionsText: 'Value', value: selectedProject"&gt;&lt;/select&gt; &lt;/td&gt; &lt;td&gt; Job: &lt;select data-bind="options: UserJobs, optionsText: 'Value', value: selectedJob"&gt;&lt;/select&gt; &lt;/td&gt; &lt;td&gt; Service: &lt;select data-bind="options: UserWorkTypes, optionsText: 'Value', value: selectedWorkType"&gt;&lt;/select&gt; &lt;/td&gt; &lt;td&gt; &lt;button data-bind="click: addProjectWorkedOn"&gt;Add Project&lt;/button&gt; &lt;/td&gt; &lt;/tr&gt; &lt;/table&gt; </code></pre> <p>and this is what displays them:</p> <pre><code>&lt;table&gt; &lt;tr&gt; &lt;td&gt;Client&lt;/td&gt; &lt;td&gt;Project&lt;/td&gt; &lt;td&gt;Job&lt;/td&gt; &lt;td&gt;Service&lt;/td&gt; &lt;td&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tbody data-bind="foreach: ListProjectsWorkedOn()"&gt; &lt;tr&gt; &lt;td data-bind="text: client.Value"&gt;&lt;/td&gt; &lt;td data-bind="text: project.Value"&gt;&lt;/td&gt; &lt;td data-bind="text: job.Value"&gt;&lt;/td&gt; &lt;td data-bind="text: workType.Value"&gt;&lt;/td&gt; &lt;td&gt;&lt;button data-bind="click: $parent.removeProjectWorkedOn"&gt;Remove&lt;/button&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; </code></pre> <p>Thanks in advance!</p> <p>EDIT: </p> <p>I worked it out</p> <p>to add project set the attributes like this: project.clientValue(self.selectedClient().Value);</p> <p>then to reference them in view call it as a function: clientValue()</p> <p>credit goes to Chris Patt for explaining that observables should be called as functions when you want to get their value</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload