Sandcar
Sandcar

Reputation: 892

Backbone.js and local storage . A "url" property or function must be specified

I'm improving my knowledge about Backbone.js and have this code sample taken from a tutorial. (http://bardevblog.wordpress.com/2012/01/16/understanding-backbone-js-simple-example/)

This example will not access the server for now, so to simulate the retrieval of data from the server I have a file name movies.json.

What I am trying to do:

My issues:   I'm having an error "Uncaught Error: 'url' property or function must be specified" when I call refreshFromServer (). I do not understand why because I set the url collection. (url : "scripts/data/movies.json" )

Sample code

var Theater = {
    Models : {},
    Collections : {},
    Views : {},
    Templates : {}
}

Theater.Models.Movie = Backbone.Model.extend({})
Theater.Collections.Movies = Backbone.Collection.extend({
    model : Theater.Models.Movie,
    localStorage : new Backbone.LocalStorage("MovieStore"), // Unique name within your app.
    url : "scripts/data/movies.json",
    refreshFromServer : function() {
        return Backbone.ajaxSync.apply(this, arguments);
    },
    initialize : function() {
        console.log("Movies initialize")
    }
});

Theater.Templates.movies = _.template($("#tmplt-Movies").html())

Theater.Views.Movies = Backbone.View.extend({
    el : $("#mainContainer"),
    template : Theater.Templates.movies,

    initialize : function() {

        this.collection.bind("reset", this.render, this);
    },

    render : function() {
        console.log("render")
        console.log(this.collection.length);

    }
})

Theater.Router = Backbone.Router.extend({
    routes : {
        "" : "defaultRoute"
    },

    defaultRoute : function() {
        console.log("defaultRoute");
        Theater.movies = new Theater.Collections.Movies()
        new Theater.Views.Movies({
            collection : Theater.movies
        });
        Theater.movies.refreshFromServer();
        //Theater.movies.fetch();
        console.log(Theater.movies.length)
    }
})

var appRouter = new Theater.Router();
Backbone.history.start();

Notes:

I can see the json list correctly in my view

Upvotes: 3

Views: 3865

Answers (1)

jevakallio
jevakallio

Reputation: 35920

Err... my bad. The refreshFromServer implementation is from my answer to your earlier question., and it's completely, uselessly wrong.

Backbone.sync expects arguments (method, model, options), but as it stands, it doesn't get what it needs from refreshFromServer because the refresh method simply sends forward whatever arguments it gets. Sorry for the mistake.

The correct, working implementation would be:

refreshFromServer : function(options) {
    return Backbone.ajaxSync('read', this, options);
}

It can be used either via success / error callbacks passed to the options hash:

this.collection.refreshFromServer({ success: function() { /* refreshed... */ });

Or via the jqXHR Promise API:

this.collection.refreshFromServer().done(function() { /* refreshed... */ })

Or not signing up for callbacks and waiting for the collection reset event like in your example:

this.collection.bind("reset", this.render, this);
this.collection.refreshFromServer();

This should work. Please let me know if it doesn't. I fixed my answer in the previous question too, in case someone stumbles onto it.

Edit: To save the data to local storage after refreshing you need to manually save each of the models:

var collection = this.collection;
collection.refreshFromServer({success: function(freshData) {
    collection.reset(freshData);
    collection.each(function(model) {
        model.save();
    });
}});

Upvotes: 4

Related Questions