Mapping knockout - transforming JSON data into view models

My api endpoint is located at /api/pin and it returns JSON data in the following format:

{
  "num_results": 4,
  "objects": [
    {
      "id": 1,
      "image": "http://placekitten.com/200/200/?image=9",
      "title": "Test"
    },
    {
      "id": 2,
      "image": "http://placekitten.com/200/200/?image=9",
      "title": "test"
    },
    {
      "id": 3,
      "image": "www.test.com",
      "title": "test"
    }
  ],
  "page": 1,
  "total_pages": 1
}

I am trying to populate a knockout observable array using this data and display it on my page. Here is my JavaScript file snippet:

define(['knockout', 'text!./pins.html'], function(ko, templateMarkup) {

function Pins(params) {
    var self = this;
    self.agents  = ko.observableArray([]);

    $.getJSON('/api/pin', function(data){
        self.agents = ko.mapping.fromJS(data);
    });
 }


return { viewModel: Pins, template: templateMarkup };

});

Here is my HTML code:

<b data-bind="agents.num_results"> results </b>
<table>
    <tbody data-bind="foreach: agents.objects">
        <tr>
            <td data-bind="text: image"></td>
            <td data-bind="text: title"></td>
        </tr>     
    </tbody>
</table>

Currently, I am only seeing the word "results" rendered on my page and nothing else. I have successfully created a view model that represents the JSON data and added it into the array during the getJSON call. However, I believe the purpose of the knockout mappings library is to handle this automatically without manual creation of view models. I seem to be missing something obvious here and struggling to identify the issue.

Answer №1

After some trial and error, I managed to come up with a PinViewModel setup that did the trick:

define(['knockout', 'text!./pins.html'], function(ko, templateMarkup) {

    function PinVewModel (){
      this.objects = ko.observableArray();
    }

    function Pins(params) {
        var self = this;
        self.agents   = new PinVewModel();

        $.getJSON('/api/pin', function(data){
            ko.mapping.fromJS(data, {}, self.agents);
        });
     }

   return { viewModel: Pins, template: templateMarkup };

   });

If anyone wants to know about the POST functionality...

  function Pin(data){
    this.image = ko.observable(data.image);
    this.title = ko.observable(data.title);
  }

  this.createPins = function(formElement){
     formPin = new Pin({image: formElement.pin_url.value, title: formElement.pin_name.value});

    $.ajax("/api/pin", {
        data: ko.toJSON(formPin),
        type: "post",
        contentType: "application/json",
        success: function(result) { 
            self.pins.objects.push(formPin);
        }
    });     
};

There may be some redundancy in my approach, but it does the job and gets the desired results.

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

Type for the key in array.reduce that is not specific or unique

Given an array of objects, I use the reduce method to transform it into a new format where each key represents a date from the original array. For example, if the array contains objects with dates like {date: '22-02-06-00:55:66', name: 'one& ...

steps for linking a directive variable to a controller

Encountering an issue with 2-way binding in Angular where changes made to the input do not reflect in the controller. However, the initial value set by the controller does affect the directive. In the screenshot, a value was changed but vm.date still hold ...

Using Google Apps Script to invoke a JavaScript function from an HTML file

In my Apps script project, I am working on creating a Google chart that will appear in a modal above Google Sheets. I have ChartC.html: <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> ...

What is the best way to separate axios functions and components in Vue3?

In my opinion, it's more efficient to separate the axios commands from the vue components. This is how I structured my directories: src api - products.js components - Products.vue products.js import axios from 'axios'; const li ...

Using Mapbox GL JS to Showcase Latitude and Longitude Coordinates

I successfully added a feature to display the LAT LON readout of the cursor location on my website by following the tutorial provided in This Mapbox GL JS Tutorial However, the output I receive is in this format: {"lng:-74.949147382928,"lat":40.438292204 ...

Utilizing Jquery to locate a link inside a Div and displaying it as specified in the HTML

Looking for a solution to make div elements clickable as links? The usual methods involving window.location or window.open may not be suitable if you have numerous divs with predefined targets. If you're not well-versed in Javascript, finding the righ ...

Accessing deeply nested JSON objects in AngularJS

I've been working on an AngularJS single page application and I have successfully fetched files from a JSON. var app = angular.module("MyApp", []); app.controller("TodoCtrl", function($scope, $http) { $http.get('todos.json'). success ...

Provide a numerical representation of how frequently one object value is found within another object value

Account Object Example in the Accounts Array: const accounts = [ { id: "5f446f2ecfaf0310387c9603", picture: "https://api.adorable.io/avatars/75/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0e6b7d7a666 ...

There was an AJAX post error that occurred due to the refusal to set an unsafe header with the name "Connection"

My custom ajax function sends data to a PHP file, but I'm encountering two errors each time the data is posted: Refused to set unsafe header "Content-length" Refused to set unsafe header "Connection" Here is my code: function passposturl(url1 ...

Tips for accelerating the loading of data retrieved through ajax requests

At present, data is being fetched in array form from a PHP script. I have noticed that when retrieving 40 sets of data, it takes approximately 20 seconds for the data to load. This delay may be due to ajax having to wait until all the results are gathered. ...

Encountering a 404 error when attempting to use the jQuery .load() function with parameters that include periods ('.')

I am attempting to invoke a controller function using the .load() method, but encountering an error which might be caused by the encoding of '.'. The call I am making is as follows: $("#main-content").load( url + "/" + encodeURIComponent(text ...

Evaluate the functionality of an Angular controller method that interacts with the Document Object Model (

We currently have an AngularJS controller that contains the following function: $scope.testMe = function() { return $('#test'); } So, how can we effectively test this function? We attempted a Karma test as shown below: describe(' ...

A guide on incorporating multiple nested loops within a single table using Vue.js

Is it possible to loop through a multi-nested object collection while still displaying it in the same table? <table v-for="d in transaction.documents"> <tbody> <tr> <th>Document ID:</th> &l ...

The battle between dynamic PDF and HTML to PDF formats has been a hot

In my current project, I am developing multiple healthcare industry dashboards that require the functionality to generate PDF documents directly from the screen. These dashboards do not involve typical CRUD operations, but instead feature a variety of char ...

What are the circumstances under which JavaScript GCP libraries return null values?

My current project involves working with GCP and Firebase using typescript. I have been utilizing the provided libraries, specifically version 8 of Firebase, and have encountered some unexpected behavior. For instance (firebase, ver. 8.10.1) import 'f ...

Update the field 'payments._id' in MongoDB to a timestamp

I need to change the value of 'payments._id' to a timestamp. In MongoDB, the 'payments._id' object is automatically generated when inserting a document into the collection. onMounted(async () => { const res = await axios.get(" ...

Is it possible to utilize window.location.replace function within an iframe?

Is it possible to use window.location.replace to bypass history and target on-page anchors without page reloads, but encounter issues when working within iframes? The main problem seems to be a CSP (content security policy) violation for script-src ' ...

JavaScript GridView

Is there a way to determine if an ASP.NET GridView contains at least one row by using JavaScript? ...

Python code that retrieves information from an Excel spreadsheet and organizes it into tree structures

I currently have a Python script that is designed to extract data from an Excel file, specifically focusing on information from three distinct columns: Finished Good, Parent Part Code, and Material Code. The structure of these columns is outlined below: Ma ...

Tips for including a new class in an HTML element

My goal is to add a specific class to an HTML tag, if that tag exists. This is the code I have attempted: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>index</title> <style> ...