4

I am relatively new in the backbone library. I'm trying to build a mobile application based on backbone + requirejs + jquery-mobile. I can fill my collection with existing json local file. (in the future may come from a remote server). Now I'm trying to get this collection to be called only once and then storing it in localStorage for read. for this I am trying to use this adapter (https://github.com/jeromegn/Backbone.localStorage) but I do not understand how.

Sample code

// models
define([
  'underscore',
  'backbone'
], function(_, Backbone) {
  var AzModel = Backbone.Model.extend({
    defaults: {
      item: '',
      img:"img/gi.jpg"
    },
    initialize: function(){
    }
  });
  return AzModel;
});

// Collection
define(['jquery', 'underscore', 'backbone', 'models/az'], function($, _, Backbone, AzModel) {
    var AzCollection = Backbone.Collection.extend({
     localStorage: new Backbone.LocalStorage("AzStore"), // Unique name within your app.       
    url : "json/azlist.json",
    model : AzModel
    parse : function(response) {
         return response;
    }
});

return AzCollection;
});

define(['jquery', 'underscore', 'backbone', 'collections/azlist', 'text!templates/karate/az.html'], function($, _, Backbone, AzList, AzViewTemplate) {
    var AzView = Backbone.View.extend({
        id:"az",
        initialize: function() {
            this.collection = new AzList(); 
            var self = this;
            this.collection.fetch().done(function() {
                //alert("done")
                self.render();
            }); 

        },
        render : function() {
            var data = this.collection;
            if (data.length == 0) {
                // Show's the jQuery Mobile loading icon
                $.mobile.loading("show");
            } else {
                 $.mobile.loading("hide");
                console.log(data.toJSON());
                  this.$el.html(_.template(AzViewTemplate, {data:data.toJSON()}));
                  // create jqueryui
                 $(document).trigger("create");
            }
            return this;
        }
    });
    return AzView;
});

Does someone can point me the way.

PaulStock
  • 11,053
  • 9
  • 49
  • 52
Sandcar
  • 892
  • 1
  • 9
  • 21

1 Answers1

5

The Backbone local storage adapter overrides Collection.sync, the function which is used when you fetch the collection, or save models within the collection. If you set the Collection.localStorage property, it redirects the calls to the local storage instead of the server. This means you can have either or -- read and write to local storage or server -- but not both at the same time.

This leaves you two options:

  1. Do the initial fetch, which populates the data from the server, and only then set the localStorage property:

    var self = this;
    
    self.collection.fetch().done(function() {
        self.collection.localStorage = new Backbone.LocalStorage("AzStore");
        self.render();
    }); 
    
  2. Set the Collection.localStorage property as you do now, and fetch the initial dataset manually using Backbone.ajaxSync, which is the alias given to Backbone.sync by the localstorage adapter:

    Backbone.ajaxSync('read', self.collection).done(function() {
        self.render();
    }
    

The latter option might be preferrable, because it doesn't prevent you from loading the data from the server later on, if required.

You could quite neatly wrap the functionality as a method on the collection:

var AzCollection = Backbone.Collection.extend({
    localStorage: new Backbone.LocalStorage('AzStore'),
    refreshFromServer: function() {
        return Backbone.ajaxSync('read', this);    
    }    
});

When you want to load data from the server, you can call that method:

collection.refreshFromServer().done(function() { ... });

And when you want to use the local storage, you can use the native fetch:

collection.fetch().done(function() { ... });

Edited to correct mistake in sample code for the benefit of drive-by googlers.

jevakallio
  • 35,324
  • 3
  • 105
  • 112
  • I'm pretty sure that I saw an updated localStorage plugin that lets you save to either, I'm going to try and find a link. – Jack Dec 28 '12 at 15:10
  • OK I found what I was referring to, it's [backbone.offline](https://github.com/Ask11/backbone.offline) (I haven't used it myself I just remembered reading about it). – Jack Dec 28 '12 at 15:13
  • thanks for your reply Fencliff. 've Helped me a lot. I am implementing the second option "refreshFromServer" but when I call this method, I have an error "The 'url' property or function must be specified." Any idea why this happen?   Thank you – Sandcar Dec 28 '12 at 15:34
  • Thanks for the link @jack. I'll take a look to see if it helps – Sandcar Dec 28 '12 at 15:36
  • @Sandcar, the collection must have a url property on order for Backbone to know where to ask for the data. See docs. – jevakallio Dec 29 '12 at 07:43
  • Fencliff, when I saw this error "The url property or function ..." I tried to figure, where the problem might lie. I googled and Also try to find an answer on docs. In the example code I am setting the url property in the collection (path to a local Json file for now). i now that I'm missing something (probably simple) but I can not get there.   Thanks for your patience – Sandcar Dec 29 '12 at 20:50
  • For those who need more info please see [this question](http://stackoverflow.com/questions/14277010/backbone-js-and-local-storage-a-url-property-or-function-must-be-specified) too. Many thanks to @fencliff for all the effort in pointing the right way – Sandcar Jan 12 '13 at 14:23
  • hey this is good way, but i guess it even after fetching from server we declare localstorage but its size still remains 0, as the fetched data does not gets populated into localstorage – Suyog Sawant Dec 06 '14 at 07:52