How can we enhance Backbone.sync() at the Model level to include additional parameters?

Currently, I am facing a challenge with overriding Backbone's sync() method for a Model. I have the function signature set up and it is triggered correctly, but I am unsure about what needs to be included in the function body in order for it to automatically send a default DELETE call along with additional arguments.

class Master.Models.Member extends Backbone.Model
  urlRoot: '/api/members/'

  sync: (method, model, options) ->
    params = _.clone options
    Backbone.sync method, model, params

When using this code:

......
remove: ->
  @model.destroy
    collective_id: the_id

The goal here is to pass the collective_id parameter to the server. However, even though it is included in the options hash for sync() and I clone it, the parameter does not make it to the server! Is there a way to successfully send that extra param to the server?

(Currently, only the Model's id is reaching the server)

Thank you in advance for any assistance!

Answer №1

When you invoke .destroy(), .fetch() or .save(), they all trigger Model.sync which ultimately invokes Backbone.sync. Acting as a proxy function, this allows for easy manipulation of the AJAX behavior of a single model or any models that inherit from it.

  • Solution 1: Replace the Global Backbone.sync with JSON.stringify and adjust the contentType when sending data with the delete request.
    • Pros: Ability to call model.destroy() and pass an optional options parameter.
  • Solution 2: Override the Model.sync method directly.
    • Pros: The override is specific to individual models, leading to isolated changes.
    • Cons: Models requiring data deletion need to extend from the correct 'base model'.
  • Solution 3: Refrain from overriding and instead manually invoke model.sync with appropriate stringify and contentType.
    • Pros: Changes are contained within the specific model, without impacting others. Particularly useful in large codebases integration scenarios.

[Solution 1] - Modifying Global Backbone.sync (all models affected)

Javascript version:

var oldBackboneSync = Backbone.sync;
Backbone.sync = function( method, model, options ) {
    // Ensure data is formatted properly for DELETE requests
    if ( method === 'delete' && options.data ) {
        options.data = JSON.stringify(options.data);
        options.contentType = 'application/json';
    } // Otherwise follows normal flow
    return oldBackboneSync.apply(this, [method, model, options]);
}

Usage:

var model, SomeModel = Backbone.Model.extend({ /* urlRoot, initialize, etc... */});
model = new SomeModel();
model.destroy({
    data: {
        /* data payload to send with delete request */
    }
});

[Solution 2] - Customizing Backbone.destroy on base model for extensions

Override Example:

// Create custom 'enhanced' model 
Backbone.EnhancedModel = Backbone.Model.extend({
    destroy: function( options ) {
        if ( options.data ) {
            // Format data appropriately for backend parsing
            options.data = JSON.stringify(options.data);
        }
        // Set content type for DELETE requests to application/json
        options.contentType = 'application/json';
        Backbone.Model.prototype.destroy.call(this, options);
    }
});

Usage:

var model, SomeModel = Backbone.EnhancedModel.extend({ /* urlRoot, initialize, etc... */})
model = new SomeModel();
SomeModel.destroy({
    data: {
        /* additional data payload */
    }
}); 

[Solution 3] - Explicit invocation of .destroy() with necessary parameters

If handling data in destroy requests separately, this approach works effectively.

When utilizing model.destroy(), include data and contentType options like so:

Javascript version/usage:

var additionalData = { collective_id: 14 };
model.destroy({
    data: JSON.stringify(additionalData),
    contentType: 'application/json'
});

The "Issue" (regarding Backbone, not solutions):

Backbone.js assumes (view source) that delete requests should not contain a data payload.

// Data processing and content type alteration excluded for delete methods
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
      params.contentType = 'application/json';
      params.data = JSON.stringify(options.attrs || model.toJSON(options));
}

In its expected RESTful API call, only the ID needs to be included in the request, appended via the urlRoot property.

var BookModel = Backbone.Model.extend({
    urlRoot: 'api/book'
});
var book1 = new BookModel({ id: 1 });
book1.destroy()

The resulting DELETE request would be:

DELETE => api/book/1
contentType: Content-Type:application/x-www-form-urlencoded; charset=UTF-8

Answer №2

Make sure to send parameters in the options.data field, like this:

typescript

remove: () => {
  this.model.destroy({
    data: JSON.stringify({
      collective_id: the_id
    }),
    contentType: 'application/json'
  });
}

python

remove():
  self.model.destroy(
    data = json.dumps({
      collective_id: the_id
    }),
    content_type = 'application/json'
  )

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

Discover the ultimate guide to maintaining individual premium memberships in a Next.js application using the powerful combination of Redux, Firebase, and Stripe. Never worry about users losing their premium status again after

I have integrated Stripe for users to purchase premium subscriptions, but I am facing an issue with storing their premium status in Redux Persist State. After they log out, the state refreshes and upon logging back in, they are required to purchase a premi ...

Executing a JavaScript function by utilizing the # symbol in the URL: Tips and Tricks

It all began with a function called loadround that changed the innerHTML of an iframe. The links within the iframe would then change the page when clicked, but hitting the back button made the loadround page vanish. I pondered over this issue multiple time ...

The ng-bootstrap datepicker does not allow setting a default date prior to selection

I have implemented the ng-bootstrap date picker in my project and I am facing an issue with setting a default date for the input field before selecting a date from the datepicker itself. <input type="text" id="datepicker{{i}}" class="form-control" form ...

Integrate an item into the request body utilizing the $.load() function in jQuery

Currently, I am using a POST request via jQuery's $.load function to retrieve data to display in a window. This is what I am currently doing: var testObject = { thing1: 'data1', thing2: 'data2', thing3: &a ...

Launch the sidebar window using jQuery

I've been attempting to create something similar to this. However, I'm having trouble replicating it exactly. What I've attempted I've managed to create a replica, but the issue is that the buttons are fixed. Could setting the left ...

Whenever I declare it, the onclick method is executed

I have been attempting to define an onclick method that would trigger a function to clear and reconstruct the display, revealing more detailed information about the clicked item. However, I am facing an issue where the assigned onclick method is executed i ...

In React, components will consistently render the initial code

I have a chat application that requires authentication and uses cookies. Here's what I've been attempting: class AppHeader extends React.Component { constructor(props) { super(props) } render() { if (cookies.get(' ...

Leveraging AngularJS services within an Angular service

I am currently in the process of transitioning my AngularJS application to Angular. To facilitate this transition, I plan to create a hybrid application that combines both frameworks until the conversion is complete. However, I have encountered an issue wi ...

Transferring information between Express and React through the Contentful API

I have embarked on a journey to explore Contentful's headless CMS, but I am encountering a challenge with their API client. My goal is to combine Express with React for server-side rendering, and I am utilizing this repository as my starting point. S ...

The reactivity of Vuex and Vue does not work as expected when a dictionary is used as a

What is the best approach to make a dictionary reactive as one of my store variables? Unlike an array, dictionaries are not reactive by default. Here's a minimal example I've created: Check out this example on CodeSandbox ...

What are the steps to make React JSX direct to "/profile" and display the profile page?

Throughout my application, I have integrated reach router to facilitate navigation between the different pages. However, I came across a navbar component that I really like and decided to add it to my app. Strangely, clicking on the "to: "/profi ...

Typescript error handling: Handle 404s on all Koa routes

Issue Encountering problems while setting up Auth Controllers Difficulty using Bcrypt and JWT for encryption All POST Calls to Koa resulting in 404 errors Calls to other routes are functioning correctly Potential issue with the scope of the code. impo ...

Manipulating a global variable in VueJS

Currently, I am referring to Global data with VueJs 2 for my project, focusing on only one variable. In the code provided, I have included an @click event to update the variable. However, it throws an error stating "Uncaught ReferenceError: $myGlobalStuff ...

Identifying an anonymous function with a name (using .name versus .displayName)

In the context of my react native project, I have come across a function with an undefined name that is not being inferred. This function looks like: const f = function() {}; Despite maintaining its anonymous definition, there is an attempt to assign a na ...

What impact do the input values of an Angular reactive form have on the DOM?

I am currently working on developing a UI wizard app using Angular (reactive forms) version 6/7. The main purpose of this app is to enhance the product page of an ecommerce platform such as Shopify or WordPress. I am utilizing angular material radio inputs ...

Changing the background color of .pane and .view elements in an Ionic web application using JavaScript

Looking to modify the background-color of two css selectors, .pane and .view, that are located within the ionic.css file. Despite multiple attempts to do so using JavaScript directly in the index.html file, the changes are not reflected. The code snippet ...

Creating fixed values in HTML

I need to maintain consistency in the headings of multiple tables spread across 3 HTML pages. The heading structure is as follows: <thead> <tr> <th>MyHeading</th> </tr> </thead> My goal is to store the string MyHeadin ...

ReactJs - The pagination feature in MaterialTable is malfunctioning, it is not displaying the correct

I am currently utilizing the Material-table plugin. It successfully displays the data, however, I am facing issues with Pagination and Row per Page dropdown functionality. When trying to click on the next button or select a number of rows, nothing happens. ...

Navigating through the realm of Android development entails understanding how to manage a multi-object function in JavaScript when using

In order to load an HTML page using the webview component and handle its functions, I am faced with a challenge. The HTML page contains a multi-object named (webkit.messageHandlers.adClicked). How can I utilize the webView.addJavascriptInterface() functi ...

Can someone please provide me with a Javascript code snippet that accomplishes the same function

<script> document.addEventListener('DOMContentLoaded', function () { const menuItems = document.querySelectorAll('.headmenu li'); menuItems.forEach(function (menuItem) { menuItem.addEventL ...