Create new instances of Backbone Models using an existing Backbone Model as a template

Within my app, I am planning to include a configuration file called config.json as a Backbone Model. Here is an example of how it will be loaded:

var Config = Backbone.Model.extend({
    defaults: {
        base: ''
    },
    url: 'config.json'
});

Furthermore, I want other models to rely on certain data from Config. For instance, consider the following scenario:

var ModelA = Backbone.Collection.extend({
    initialize: function(){
        //this.url should be set to Config.base + '/someEndpoint';
    }
});

In this particular case, the url property of ModelA is dependent on the value of base from the Config object.

How can I properly establish this setup within a Backbone application?

Answer №1

From my perspective, it seems that your primary queries include:

  • How can we obtain an instance of the configuration model?
  • How do we utilize the configuration model to set the dependent model's url?
  • How can we ensure that we do not use the url function on the dependent model prematurely?

There are numerous approaches to tackle this issue, but I will propose some specific solutions to offer guidance and code for a smooth implementation.

My recommendation for addressing the initial challenge is to create the configuration model as a singleton. Below, I will include code snippets from the backbone-singleton GitHub page for reference.

var MakeBackboneSingleton = function (BackboneClass, options) { ... }

Subsequently, we establish a singleton named AppConfiguration and a deferred property utilizing jQuery. The outcome of fetch will provide callbacks such as always(callback) and done(callback).

var AppConfiguration = MakeBackboneSingleton(Backbone.Model.extend({
    defaults: {
        base: null
    },
    initialize: function() {
        this.deferred = this.fetch();
    },
    url: function() {
        return 'config.json'
    }
}));

Next, we define the dependent model DependentModel, which mirrors your model. This model will invoke AppConfiguration() to acquire the instance.

Due to the implementation of MakeBackboneSingleton, the following statements hold true:

var instance1 = AppConfiguration();
var instance2 = new AppConfiguration();
instance1 === instance2; // true
instance1 === AppConfiguration() // true

The model will automatically initiate a fetch operation upon receiving an id, but only after the completion of the AppConfiguration's fetch. Various callbacks such as always, then, and done can be utilized.

var DependentModel = Backbone.Model.extend({
    initialize: function() {
        AppConfiguration().deferred.then(function() {
            if (this.id)
                this.fetch();
        });
    },
    url: function() {
        return AppConfiguration().get('base') + '/someEndpoint';
    }
});

Finally, by integrating all components, you can instantiate models as follows:

var newModel = new DependentModel();   // no id => no fetch

var existingModel = new DependentModel({id: 15}); // id => fetch AFTER we have an AppConfiguration

The second instantiation will trigger an auto-fetch operation only if the AppConfiguration's fetch was successful.

Below is the implementation of MakeBackboneSingleton sourced from the GitHub repository:

var MakeBackboneSingleton = function (BackboneClass, options) {
    options || (options = {});

    // Helper to check for arguments. Throws an error if passed in.
    var checkArguments = function (args) {
        if (args.length) {
            throw new Error('cannot pass arguments into an already instantiated singleton');
        }
    };

    // Wrapper around the class. Allows us to call new without generating an error.
    var WrappedClass = function() {
        if (!BackboneClass.instance) {
            // Proxy class that allows us to pass through all arguments on singleton instantiation.
            var F = function (args) {
                return BackboneClass.apply(this, args);
            };

            // Extend the given Backbone class with a function that sets the instance for future use.
            BackboneClass = BackboneClass.extend({
                __setInstance: function () {
                    BackboneClass.instance = this;
                }
            });

            // Connect the proxy class to its counterpart class.
            F.prototype = BackboneClass.prototype;

            // Instantiate the proxy, passing through any arguments, then store the instance.
            (new F(arguments.length ? arguments : options.arguments)).__setInstance();
        }
        else {
            // Make sure we're not trying to instantiate it with arguments again.
            checkArguments(arguments);
        }

        return BackboneClass.instance;
    };

    // Immediately instantiate the class.
    if (options.instantiate) {
        var instance = WrappedClass.apply(WrappedClass, options.arguments);

        // Return the instantiated class wrapped in a function so we can call it with new without generating an error.
        return function () {
            checkArguments(arguments);

            return instance;
        };
    }
    else {
        return WrappedClass;
    }
};

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

Instead of returning an object, the data is returned as an array

I seem to have made a mistake somewhere, can you help me figure out what it is? I tried two different approaches: The first solution involves sending data from VsCode to the database and then retrieving it. In the second solution, I simply send a pa ...

The functionality of Jquery radio:checked is not behaving as desired

Currently, I am in the process of learning jquery. I have created a basic html file with some jquery validations, however, they are not functioning as expected. The main problem is: If I input my name first and then check the checkbox, everything works co ...

Ways to deactivate a button within a Kendo Grid cell

I am trying to include 2 buttons in a cell, where one button calls a specific function and the other button disables the previous button that calls the function. In my template column, I have implemented the following: return '<button kendo-button ...

Complete Search with the press of Enter on the Auto Textbox

I have implemented an Ajax auto complete extender on a TextBox control. As the user begins typing, suggestive options are displayed below the input field based on data retrieved from a webservice call. When OnClientItemSelected="GetCode" is triggered, the ...

An easy way to incorporate a fade-in effect for every word in a text

I am trying to make the text "Eat. Sleep. Repeat." slide up and fade in one word at a time. I have experimented with various methods like anime.js, keyframes, and adding css classes, but so far none of them have worked for me. Here is the code I currently ...

The Kendo Grid is refusing to show up within the popup window

I am new to using Angular 2 and Kendo UI. Currently, I am attempting to include a grid inside my pop-up window. While I have successfully displayed the pop-up, adding the grid has proven challenging. The grid is not appearing as expected ...

AngularJS: Issue with ng-show and ng-click not functioning when button is clicked

I have a specific requirement where I need to display and hide the description of each column in a table when a button is clicked. Here is the visual representation of what I have: the table In my HTML code, I have defined a button with ng-click as a func ...

Developing a notification system using a combination of ajax, jquery, and Iframe

I am in the process of setting up a messaging system on my website. Currently, I have a table with three columns - two integer fields (from and to) and a timestamp for the date of sending. On one section of the page, I want to display a list of messages ...

What is the best way to retrieve the [id]/routeName in Next.js?

I'm working on a straightforward project where users visit links like: localhost:3000/course/[id]. Once they click join, the URL will transform to localhost:3000/course/[id]/routeName. How can I organize folders like that within pages? Thank you in ad ...

What sets apart `Writes[MyClass]` from `Writes[MyClass.type]`?

My issue is that I've created a function which requires a Writes[Class.type] as input. However, when passing it the argument, the compiler recognizes it as Writes[Class] and fails to compile. Can someone explain the distinction between these two? ...

Is there a way to invoke a function once grecaptcha.execute() has completed running, but in response to a particular event?

Presently, the JavaScript function grecaptcha.execute is triggered on page load, as shown in the first example below. This means that the reCAPTCHA challenge occurs as soon as the page loads. A more ideal scenario would be to trigger it when the form submi ...

experimenting with adding fresh choices to dropdown menu using ajax and jquery

When attempting to load a list of locations through ajax/jQuery, I encounter an issue. After typing a letter into the input field, the first response is displayed but subsequent responses are simply appended to it. I have tried using .html('') an ...

Analyzing registration details stored in an array against user login credentials

With two buttons available - one for sign up and the other for log in, my goal is to gather input form values from the sign-up section into an array. Following this, I aim to compare the user input from the sign-up with that of the log-in, informing the us ...

Looking to retrieve the mouse coordinates using JavaScript

How can I use JavaScript to track the mouse position on a canvas? Upon visiting this page: http://billmill.org/static/canvastutorial/mouse.html They provide this code snippet: function initializeMouse() { canvasMinimumX = $("#canvas").offset().left; ...

Tips for effectively utilizing the Ngrx navigation function

While exploring NgRx, I stumbled upon navigation. According to the documentation, it seems like this effect should trigger when the component loads. However, I'm facing an issue where this effect is not getting triggered. Other effects that I've ...

Update the value of a scope variable directly within a controller. Subsequently making a function call

Hey there, I just want to start by saying sorry in case this question has already been asked or if it seems silly. I'm pretty new to AngularJS and have managed to overcome CORS errors, set up login via Parse, and even created an API for my app using ...

Issue encountered during Deserialization of JSON data

I encountered an issue at dynamic jsonText = JsonConvert.DeserializeObject(json); ERROR Unexpected character found while parsing value: <. Path '', line 0, position 0. CODE string api = "https://api.linkedin.com/v1/people/~:(id,first-nam ...

Steps for preventing form submission when the username is unavailable

After checking the availability of the user name, I encountered an issue where the form still gets submitted even if the username is not available. Updated Code: <SCRIPT type="text/javascript"> $(document).ready(function(){ $("#emailch").change(fu ...

The reflight response received an unexpected HTTP status code of 500

Recently, I've been working on utilizing the Yelp Fusion API by making a simple ajax call. I started off by using the client_id and client_secret provided by Yelp to successfully obtain an access token through a 'POST' request in Postman, fo ...

Does the method in the superclass "not exist" within this type....?

Our TS application utilizes a JavaScript library, for which we crafted a .d.ts file to integrate it with TypeScript. Initially, the file resided in a "typings" directory within the project and everything operated smoothly. Subsequently, we opted to relocat ...