Using Knockoutjs to fetch and display server-side data within the MVC framework

My goal is to initialize my knockoutjs viewmodel with data from the server. In my ASP.Net MVC project, I achieve this by passing a mvc viewmodel to the view:

public ActionResult Edit(int cvId)
{
    CV cv = repository.FindCV(cvId);

    //auto mapper mapping
    Mapper.CreateMap<CV, MyCVViewModel>();
    Mapper.CreateMap<Company, MyCompanyViewModel>();
    Mapper.CreateMap<Education, MyEducationViewModel>();
    Mapper.CreateMap<Reference, MyReferenceViewModel>();
    var model = Mapper.Map<CV, MyCVViewModel>(cv);

    return View(model);
}

Within the view, I stringify the viewmodel into JSON and bind it to the knockoutjs viewmodel for data population:

//mvc viewmodel
@model Taw.WebUI.Models.MyCVViewModel
//convert
@{
    var json = @Html.Raw(Model.ToJson());
}

//lastly bind
<script type="text/javascript">
    // Activate knockout binding
    var viewModel = new CVViewModel(@json);
    ko.applyBindings(viewModel);
</script>

In my knockout javascript file, I define how the knockout viewmodel will be populated with the fetched data:

var CVViewModel = function (data) {
    var self = this;

    //list view model
    self.title = ko.observable(data.title);
    self.statement = ko.observable(data.statement);
    self.reference = ko.observable(data.reference);
    self.companies = ko.observableArray(data.companies);
    self.educations = ko.observableArray(data.educations);
    self.references = ko.observableArray(data.references);
}

All values are successfully populated at this stage.

The resulting JSON string shows that only title and statement changes, not values within company section.

In order to save these edited values, I need to track what has been modified or deleted on the server side using MVC and entity framework.

Update

In my knockout javascript file, I have defined observables but need help defining them within the observablearray:

function Company() {
    this.companyName = ko.observable();
    this.jobTitle = ko.observable();
    this.description = ko.observable();
    this.startDate = ko.observable();
    this.endDate = ko.observable();
}

Answer №1

Here is the solution to your first question:

In order to resolve the issue, you must utilize ko.observable for each element in the array.

For instance, check out this example: jsfiddle

function CVViewModel(data) {
    var self = this;

    //list view model
    self.title = ko.observable(data.title);
    self.companies = ko.observableArray(data.companies.map(Company));
}

function Company(data) {
    if (!(this instanceof Company)){
        return new Company(data);
    }
    this.companyName = ko.observable(data.companyName || '');
    this.jobTitle = ko.observable(data.jobTitle || '');
    this.description = ko.observable(data.description || '');
    this.startDate = ko.observable(new Date(data.startDate) || '');
    this.endDate = ko.observable(new Date(data.endDate) || '');
}

By binding the company observables to the UI, each element in the array within the viewmodel will remain synchronized.

As for your second inquiry, I suggest utilizing an ORM such as breeze.js, which manages change tracking on your behalf. Breeze.js also offers a helpful tutorial that incorporates knockout.js.

Answer №2

The issue lies in attempting to update items within the ObservableArray. The purpose of an ObservableArray is simply to manage the array model, so any changes made to the companies observable will be reflected in the array as well. To modify the array items, each item within the ObservableArray must also be made Observable.

For more information on this topic, please refer to this post:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for sending a large list as Ajax data in an MVC model

My morning was spent in vain as I attempted different "workarounds" that were suggested, usually for more specific scenarios than the one I am facing. My goal is to simply pass an ASP.NET MVC model using the JQuery load method. It seems promising when I us ...

No matter how hard I try, I can't seem to get any of my jQuery events to function properly on my

Help! I'm encountering issues with jQuery on my webpage. It's not functioning at all, despite my extensive search for a solution. Feeling desperate, I'm reaching out for assistance here. Below are my HTML and JS files: HTML <html> ...

"Exploring the dynamics of optional values in Swift structures

I have been working on implementing a basic login system for my SwiftUI project, but I am facing some challenges in understanding the server response. When a user successfully logs in, the server returns the following data: "user": { ...

The page loads successfully at first, but upon refreshing, a 404 error occurs when using Zeit, Nextjs, and now

After recently updating from now v1 to v2, I encountered an issue where my pages would return a 404 error when reloading after pushing to production using now --prod. While everything worked fine locally with now dev, the routing seemed to be causing confu ...

Guide to creating dynamic borders around your PHPexcel output

Looking for assistance on adding borders around output arrays in an Excel report using PHPexcel. I reviewed the documentation, but the examples are static, requiring a predefined number to set. My goal is to have all arrays transferred to Excel with bord ...

Encountering a 404 XHR Error when attempting to add a component in Angular 4.1.0 within Plunker

Having some trouble setting up Angular 4 on Plunker and adding a new component. The following URL is where I'm working: https://plnkr.co/edit/1umcXTeug2o6eiZ89rLl?p=preview I've just created a new component named mycomponent.ts with the necessar ...

Storing HTML table data in a MySQL database will help you

Operating a website focused on financial planning where users can input various values and cell colors into an HTML table. It is crucial to uphold the integrity of these HTML tables. How can I store the complete HTML table (including values and colors) i ...

Utilize JQuery variables for toggling the visibility of various DIV elements

On my webpage's splash page, there are 4 divs but only the home div is initially visible. The other three are hidden. Each of these divs has a button associated with it that triggers a jquery click event to swap out the currently visible div for the ...

Leveraging a JavaScript variable declared outside the function to successfully transfer data to my AJAX function

Every time the enter key is pressed, my AJAX function gets executed. I used to pass a set of javascript variables equal to elements in the HTML (the contents of a text area) as data for the AJAX function. Now, I want these JS variables to hold values from ...

How to create a fresh factory instance in Angular Js

I have implemented a factory in my application to retrieve a list of folders and display it on the front end. Additionally, I have a form on the front end where users can add new folders to the existing list. After adding a folder, I need to refresh my fac ...

Styling Dropdown Options Based on Conditions in React

In my current project, I am attempting to modify the className of selected items within a mapped array using another array (this.props.notPressAble). The reason for this is because I want certain objects in the array to have a different CSS style. handleOp ...

I am facing difficulties installing packages such as react-bootstrap on my dashboard

Encountering an issue with installing packages in my dashboard. For example, attempting to install react-bootstrap results in the following error: node version: 12.16.1 npm version: 6.13.4 gyp ERR! UNCAUGHT EXCEPTION gyp ERR! stack Error: Cannot find mo ...

Selenium/c# facing issue with clicking Dynamics365 dropdown menu - getting "ElementNotVisibleException" error

Currently working on automating Dynamics365 CRM using Selenium/C#. I am able to successfully click and drop down the menu, however, I am facing issues finding and clicking on the "Submitted" option (line 2 of the code). The exception I am encountering is: ...

Despite the headers being in place, the node is still the point of

I am facing an issue with two URLs residing on the same server, mydomain.com and api.mydomain.com In order to handle access-origin in my API, I have included the following code snippet: app.use(function (req, res, next) { // CORS headers res.head ...

One creative method for iterating through an array of objects and making modifications

Is there a more efficient way to achieve the same outcome? Brief Description: routes = [ { name: 'vehicle', activated: true}, { name: 'userassignment', activated: true}, { name: 'relations', activated: true}, { name: &apos ...

Differences between throwing errors, returning error objects, and using callbacks in Javascript

Currently, I am developing an assembler and simulator for a simplistic assembly language that my computer science students use during their classes. The project is being written in JavaScript with the intention of creating a user-friendly interface in the ...

Getting request parameters within Model in Loopback can be done by accessing the `ctx`

common/models/event.json { "name": "Event", "mongodb": { "collection": "event" }, "base": "PersistedModel", "idInjection": true, "options": { "validateUpsert": true }, "http": { "path": "organizer/:organizer_id/events" }, "properties": {}, "va ...

Chrome is experiencing a delay in closing the Select Option dropdown menu

On my webpage, I have two select option buttons placed on different tabs. Whenever one button is changed, I want to update the value of the other button and assign it to a specific element like a span in the example code provided. While everything works sm ...

Learn how to obtain a response for a specific query using the `useQueries` function

Can we identify the response obtained from using useQueries? For instance, const ids = ['dg1', 'pt3', 'bn5']; const data = useQueries( ids.map(id => ( { queryKey: ['friends', id], queryFn: () =&g ...

The variable "vue" is not properly defined within the instance, yet it is being called

I'm currently working on a Vue app and encountering an issue. The onScroll function is working correctly, but when I click the button component to trigger the sayHello function, I receive an error message. The error states: "Property or method &apo ...