Model with Collection in Backbone.js

Two models and a collection are in play. The first model, JobSummary, is accompanied by the second model, JobSummaryList, which serves as a collection of JobSummary items. Additionally, there exists a model called JobSummarySnapshot that houses a JobSummaryList:

JobSummary = Backbone.Model.extend({});

JobSummaryList = Backbone.Collection.extend({
    model: JobSummary
});

JobSummarySnapshot = Backbone.Model.extend({
    url: '/JobSummaryList',

    defaults: {
        pageNumber: 1,
        summaryList: new JobSummaryList()
    }
});

Upon calling fetch on the JobSummarySnapshot object, everything is retrieved successfully... with one exception. Moving through the summaryList collection reveals that all entries are labeled as type object rather than JobSummary.

The reason behind this behavior seems logical, considering that aside from the defaults object declaration, no indication is given to recognize that the summaryList should consist of JobSummaryList elements. While manual conversion to JobSummary objects is an option, it would be preferable to achieve this automatically.

A test setup is provided (functional jsfiddle here):

// Test Data
var returnData = {
    pageNumber: 3,
    summaryList: [
        {
            id: 5,
            name: 'name1'
        },
        {
            id: 6,
            name: 'name2'
        }
    ]
}; 

// Fake Server Configuration
var fakeserver = sinon.fakeServer.create();
fakeserver.respondWith('GET', '/JobSummaryList', [200,
{
    'Content-Type': 'application/json'},
JSON.stringify(returnData)]);

var callback = sinon.spy();

// Fetching Snapshot Data
var summarySnapshot = new JobSummarySnapshot();
summarySnapshot.bind('change', callback);
summarySnapshot.fetch();
fakeserver.respond();

var theReturnedList = callback.getCall(0).args[0].attributes.summaryList;

_.each(theReturnedList, function(item) {
    console.log('Original Item: ');
    console.log(item instanceof JobSummary); // IS FALSE
    var convertedItem = new JobSummary(item);
    console.log('converted item: ');
    console.log(convertedItem instanceof JobSummary); // IS TRUE
});

An update follows below:

JobSummarySnapshot = Backbone.Model.extend({
    url: '/JobSummaryList',

    defaults: {
        pageNumber: 1,
        summaryList: new JobSummaryList()
    },

    parse: function(response) {
        this.set({pageNumber: response.pageNumber});

        var summaryList = new JobSummaryList();
        summaryList.add(response.summaryList);

        this.set({summaryList: summaryList});
    }
});

Implementing this solution has shown promise. The inquiry remains open for any additional insights or feedback.

Answer №1

It is recommended that your parse() function does not directly set() anything, but rather just returns the attributes. Backbone will handle the setting process for you. For example:

parse: function(response) {
    response.summaryList = new JobSummaryList(response.summaryList);
    return response;
}

Whatever is returned from parse() will be passed to set().

If nothing is returned (equivalent to returning undefined), it is like calling set(undefined), which may cause validation issues or other unexpected results if custom validate() or set() methods expect an object. If validation or set() fails as a result, the options.success callback in Backbone.Model#fetch() will not be triggered.

To make this process more generic and ensure that set() works with plain objects from various sources (not only server responses), consider overriding the set() method instead:

set: function(attributes, options) {
    if (attributes.summaryList !== undefined && !(attributes.summaryList instanceof JobSummaryList)) {
        attributes.summaryList = new JobSummaryList(attributes.summaryList);
    }
    return Backbone.Model.prototype.set.call(this, attributes, options);
}

You may also want to explore Backbone-relational, which simplifies working with nested collections/models within models.

edit I had forgotten to include a return statement in the set() method, the code has been updated

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

Any tips on how to effectively integrate dynamic theming in CSS?

I am currently developing a theming feature for my web application, allowing users to select a theme that will dynamically change the color of various elements. Here is an example of the theme selector: <div id="theme-selector"> <div id="theme- ...

Stop node.js from automatically converting a nested object containing numeric keys into an array

Every time I send an object with a nested object containing keys that are numbers to my node.js server, the nested object gets converted into an array. Is there a way to prevent this from happening? Client: $.ajax({ url : `/cctool/report`, method ...

Guide to retrieving a specific cell value from a gridview and showcasing it in a textbox with jquery on an asp.net platform

Below is the code for my grid view. It consists of a column labeled "Syllabus" and the next column contains edit and delete buttons. When the Edit button is clicked, a popup appears using jQuery. The popup includes a textbox for the Syllabus. How can I ret ...

Issue with series of node commands getting stuck on npx command

I have a custom node script that I use to automate the setup of my application. This script creates directories, generates files, and executes a series of node commands. Everything functions correctly for the most part. The specific commands being executed ...

Enhancing Watermark Functionality for Text Boxes

I am encountering an issue with three textboxes all having watermarks. When I use JavaScript to set the value of the second textbox in the OnChange event of the first textbox, the text appears as a watermark. However, when I click on the textbox, it become ...

As I iterate through a MySQL array, JavaScript is able to manipulate the initial displayed data

I'm struggling to achieve the desired outcome with my code. It seems that when I iterate through an array of data, JavaScript only works on the first echoed data. Here is a snippet of the code: <?php $ids = array(); ...

What is the best way to deserialize JSON into a sealed trait with Play Framework in Scala?

I'm fairly new to Scala and I've hit a roadblock with object deserialization. Any assistance would be greatly appreciated. The issue at hand involves a sealed trait Permission along with some case objects that extend it: sealed trait Permission ...

Tips for minimizing the need to copy the entire dojo library each time you create a new Java EE package for deployment on GlassFish

Currently, I am diving into comet programming and utilizing the cometd implementation along with the JavaScript dojo library before deploying my war files to GlassFish. The issue I have encountered is that every time I create a new project, I find myself i ...

Transform a JSON array into a JavaScript array

var jsonData = JSON.parse(pump_array); var name_array = []; var data_array = []; for(var i=0;i<jsonData.pumps.length;i++) { data_array.push(data_array, pump_array.pumps[i].volume); name_array.push(name_array, pump_array.pumps[i].iName);} This snippet r ...

Guide to loading a minified file in Angular 2 with Gulp Uglify for TypeScript Bundled File minimization

In my Angular 2 application, I have set the TypeScript compiler options to generate a single outFile named Scripts1.js along with Scripts1.js.map. Within my index.html file: <script src="Scripts/Script1.js"></script> <script> ...

Basic PHP code that retrieves information about visitors, such as screen resolution and country of origin

Let me share a bit about myself, as it might provide some context: I am not a professional coder. I prefer to write HTML and CSS manually using Notepad++ because I appreciate the lightweight, efficient code and enjoy having full control over my files and ...

Steer clear of receiving null values from asynchronous requests running in the background

When a user logs in, I have a request that retrieves a large dataset which takes around 15 seconds to return. My goal is to make this request upon login so that when the user navigates to the page where this data is loaded, they can either see it instantly ...

What is the best way to use jQuery to insert this block of HTML into a page from a JSON response?

<script type="text/javascript"> var dataString2 = 'run=captchagood&comment=' + comment; $.ajax({ type: "POST", url: "process.php", data: dataString2, dataType: "json", error: 'error', success: function ...

What is preventing me from being able to spyOn() specific functions within an injected service?

Currently, I am in the process of testing a component that involves calling multiple services. To simulate fake function calls, I have been injecting services and utilizing spyOn(). However, I encountered an issue where calling a specific function on one ...

Having trouble getting Google Tag Manager (GTM) to function properly on SharePoint?

I inserted the GTM code within the SharePoint Master Page body tag. <body> <--Body content goes here --> <!-- Google Tag Manager --> <noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-XXXXXXXX" he ...

Is it possible to create a multi-page single-page application using Vue js SSR?

It may appear contradictory, but I struggle to find a better way to express it. When using vue server-side rendering, it seems you are limited to single page applications. However, for various reasons, I require an application with multiple real server-s ...

Using JavaScript to choose an option within an optgroup

Is there a way to automatically select the option in the optgroup when I choose a user from the select list? Here is an example of the select code: <select name="city"> <optgroup label="Zone 1"> <option value=" ...

Ways to troubleshoot NPM installation issues related to gyp ERR

I have tried most of the suggestions found online, but I am still encountering an error when trying to install opencv and serialport. My current setup includes Visual Studio 2019 with C++ Desktop environment and Python 3.7. npm ERR! command C:\Windows ...

What causes the Number() function to increase the value of a number when the number's length exceeds 15 characters?

Every time I execute this code, the number that is returned seems to increase. Can someone please clarify why this happens? let numbers = [8, 5, 4, 9, 7, 6, 0, 2, 3, 1, 9, 7, 4] return Number(numbers.join('')) Result: 8549760231974 ...

connect a column from a separate array in pdfmake

In my current project, I am looking to link the values of an array that is different from the one present in the initial two columns. Is this achievable? (The number of partialPrice values aligns with the number of code entries). Despite several attempts ...