Using Backbone with the WordPress AJAX API

I’m attempting to build out a simple TODO plugin using Backbone and have run into an issue with the AJAX API. In order to get the correct AJAX call back you have to pass in the “action” parameter like this:

admin-ajax.php?action=get_todos

Read More

which works fine for the GET method in Backbone. However, when using DELETE Backbone will use a URL like this by default:

admin-ajax.php?action=get_todos/9

where “9” is the ID of the todo being deleted. By adding on this ID it breaks the AJAX call on the WordPress side. I can manually override the URLs for each of the methods but I’d like to know if there’s a more elegant way to get the AJAX API to work with Backbone.

I’ve created a demo plugin which shows the specific issue I’ve run in to. Load the settings page and click on any of the X’s while watching your Network inspector to see the 0 value AJAX results coming from WordPress.

https://github.com/hereswhatidid/wordpress-todo-backbone-demo

Related posts

2 comments

  1. You need to override the Backbone.sync function to change the URL used for the AJAX call. You can learn from the plugin wp-backbone does this and more. Below you can see from it how it changes all the actions into either POST or GET, create the parameters, add the action parameter and more.

    (function($) {
    Backbone.sync = function(method, model, options) {
    
        var params = _.extend({
            type:         'POST',
            dataType:     'json',
            url: wpBackboneGlobals.ajaxurl,
            contentType: 'application/x-www-form-urlencoded;charset=UTF-8'
        }, options);
    
        if (method == 'read') {
            params.type = 'GET';
            params.data = model.id
        }
    
        if (!params.data && model && (method == 'create' || method == 'update' || method == 'delete')) {
            params.data = JSON.stringify(model.toJSON());
        }
    
    
        if (params.type !== 'GET') {
            params.processData = false;
        }
    
        params.data = $.param({action:'backbone',backbone_method:method,backbone_model:model.dbModel,content:params.data});
    
        // Make the request.
        return $.ajax(params);
    
    
    };
    
    })(jQuery);
    
  2. You don’t need to override Backbone.sync since Backbone.sync will override its own $.ajax request with the parameters you pass as options. See this link for a walkthrough of how Backbone.sync works internally: http://backbonejs.org/docs/backbone.html#section-141

    You can add something like the following in your model or collection:

    save: function(){
        var $params = {
            emulateJSON: true, 
            data: { 
                     action: 'your_wp_ajax_action', 
                     payload : this.toJSON() 
                  } 
            };
    
        //return $.post(this.url, $params, null);
    
        return Backbone.sync( 'create', this, $params );
    }
    

    And then process the data as regular post data on the server side (with your model/models in $_POST['payload']).

    This method does:

    • create an array of the necessary overrides for the ajax call.
    • turn on ‘classic POST’ with the emulateJSON param: it makes for a leaner syntax on both the frontend and backend. You would have to use JSON.stringify on the ‘data’ param otherwise.
    • return the result of a call to Backbone.sync, with a default configuration of ‘create’ (POST), a dataset of {model} or {models} if a collection, and our own overrides.

    $_POST['payload'] then contains an array of all your Backbone data.

Comments are closed.