Backbone model data in collection not getting saved to localstorage

1.6k views Asked by At

I made a toy application to store racing times into localStorage entered by way of HTML input text fields. When I click "Add Race" (save basically) to store a new race's information, the model data that was instantiated when the collection was first created seems to get replaced by the new race information. It's like the collection.fetch() call is destroying any existing collection data. I want to just add a race model data into an existing collection of models. What am I doing wrong?

app.js

 // js/app.js

  var app = app || {};

  var r_obj_arr=[new app.RaceModel({race_name:'Race1', race_date: new Date('November 25, 2013'), race_time: '1:00:01', race_distance: '10K'}), new app.RaceModel({race_name:'Race2', race_date: new Date('November 28, 2013'), race_time: '2:00:01', race_distance: '15K'})];



  // Create our global collection of **Races**.

  app.Races = new RaceList(r_obj_arr);



  $(function() {



    // Kick things off by creating the **App**.

    new app.RaceView({model: r_obj_arr[0], collection: app.Races});



  });

racemodel.js

// Race Model

// ----------

// Our basic **Race** model with default attributes

var app = app || {};

app.RaceModel = Backbone.Model.extend({

  initialize: function(attributes) {

    this.race_name = attributes.race_name;

    this.race_date = attributes.race_date;

    this.race_time = attributes.race_time;

    this.race_distance = attributes.race_distance;

  },

  // Default attributes ensure that each todo created has `title` and `completed` keys.

  defaults: {

    race_name: 'default race name',

    race_date: new Date("October 25, 2013"),

    race_time: '1:06:25',

    race_distance: '5K'

  }

});

races.js

var app = app || {};



  // Race Collection

  // ---------------



  // The collection of Races is backed by *localStorage* instead of a remote

  // server.

  var RaceList = Backbone.Collection.extend({

    initialize: function() {

    },

    // Reference to this collection's model.

    model: app.RaceModel,



    // Save all of the race items under the `"races-backbone"` namespace.

    localStorage: new Backbone.LocalStorage('races-backbone'),



  });



  // Create our global collection of **Races**.

  app.Races = new RaceList();

raceview.js

var app = app || {};

app.RaceView = Backbone.View.extend({

  // Instead of generating a new element, bind to the existing skeleton of

    // the App already present in the HTML.

    el: '#race-display',



    model: app.RaceModel,



    collection: app.Races,



    // Our template for the line of statistics at the bottom of the app.

    raceTemplate: _.template( $('#racetemplate').html() ),

    // Delegated events for displaying new questions, and clearing existing ones

    events: {

      'click #add_id': 'addRace'

    },

    // The RaceView listens for changes to its model, re-rendering. Since there's

    // a one-to-one correspondence between a **Question** and a **RaceView** in this

    // app, we set a direct reference on the model for convenience.

    initialize: function() {

        // http://stackoverflow.com/questions/6079055/why-do-bindall-in-backbone-js-views

        _.bindAll(this, 'render','addRace');

        this.collection.bind('add', this.render);

        this.collection.bind('reset', this.render);

        this.render();

    },



    render: function(){

        //_.extend is an underscore.js method to combine multiple JSON objects into one

        this.$el.html(this.raceTemplate(_.extend({},this.model.toJSON(),{collection_obj: this.collection})));

        return this;

    },



    addRace: function() {

        var racename = this.$('#race-name-'+this.collection.length).val();

        var racedate = new Date(this.$('#race-date-'+this.collection.length).val());

        var racetime = this.$('#race-time-'+this.collection.length).val();

        var racemodel = new app.RaceModel({race_name: racename, race_date: racedate, race_time: racetime});

        this.collection.add(racemodel);

        racemodel.save(); 

        this.collection.fetch();  //refresh from localStorage

        alert("Running data added to collection...");

    }

});

index.html

<body>
//: some other stuff
 <div class="container">

      <div class="row">

        <h1>Running Times</h1>



        <div id="race-display">



        </div>

      <script type="text/template" id="racetemplate">

        <input type="button" id="add_id" value="Add Race" />

        <% for(var i=0; i<this.collection.models.length; i++) { %>

          <div class="col-md-3">

          <input id="race-name-<%= i %>" placeholder="Name of race?" type="text" value="<%= this.collection.models[i].get('race_name')%>" />

          <input id="race-date-<%= i %>" placeholder="Date of race?" type="text" value="<%= this.collection.models[i].get('race_date')%>" />

          <input id="race-time-<%= i %>" placeholder="Time to finish race?" type="text" value="<%= this.collection.models[i].get('race_time')%>" />

          </div>

        <% } %>

         <div class="col-md-3">

            <input id="race-name-<%= this.collection.models.length %>" placeholder="Name of race?" type="text" />

            <input id="race-date-<%= this.collection.models.length %>" placeholder="Date of race?" type="text" />

            <input id="race-time-<%= this.collection.models.length %>" placeholder="Time to finish race?" type="text" />

          </div>



      </script>

      </div> <!-- row -->





    </div> <!-- /container -->

    <script src="js/libs/jquery/jquery-min.js"></script>

    <script src="js/libs/underscore/underscore-min.js"></script>

    <script src="js/libs/backbone/backbone-min.js"></script>

    <script src="js/libs/backbone/backbone.localStorage.js"></script>

    <!-- <script src="js/libs/backbone/localStorage.js"></script> -->

    <!-- <script src="js/libs/backbone/backbone-optamd3-min.js"></script> -->

    <script src="js/models/racemodel.js"></script>

    <script src="js/collections/races.js"></script>

    <script src="js/views/raceview.js"></script>

    <script src="js/app.js"></script>
  </body>
1

There are 1 answers

2
EmptyArsenal On

In your raceview, you need to change your addRace function to create a new race model. You just keep changing the same model rather than creating a new one.

You should have some code something like this:

addRace: function() {
  var race = new racemodel({
    // code for model details
  });
  this.collection.add(race);
}