Search code examples
javascriptbackbone.jsunderscore.jsurl-routing

Backbone routing


I am creating an app that will list the days of an event as buttons, then let you add dates and click each date to get a new "daily calendar".

This is my first real world app using backbone and underscore, so I keep running into road blocks. I would really appreciate anyone helping me out.

I am now at the point where my collection is full of dates, and I can add to those dates. Now what I am trying to figure out it routing the links to switch out the calendar, depending on the selected date.

Heres what I have relating to this part of the app so far:

Collections

var Days = Backbone.Collection.extend({
  url: daysURL
});

var Calendar = Backbone.Collection.extend({
    url: URL
});

Models

var Header = Backbone.Model.extend();
var header = new Header();

var ConferenceDay = Backbone.Model.extend();
var conferenceDay = new ConferenceDay();

View

 var HeaderView = Backbone.View.extend({
  el: $(".conf_days"),
  template: _.template($('#days').html()),
  events: {
      'click a.day-link': 'changeDay',
      'click #add_day' : 'addDay',
      'click #previous_day' : 'prevDay',
      'click #next_day' : 'nextDay',
      'click #delete_day' : 'deleteDay'
    },
    initialize: function(){
      _.bindAll(this, "render");
      this.collection = new Days();
      this.collection.fetch();
      this.collection.bind("reset", this.render, this);
    },
    render: function(){
      var JSONdata = this.collection.toJSON();
      this.$el.html(this.template({days: JSONdata}));

      console.log(JSON.stringify(JSONdata))
      return this;

    },
    changeDay: function(e){

      AppRouter.history.navigate($(this).attr('href'));
      return false;

    },
    addDay: function() {
      newDate = Date.parse($('.day-link:first-child').text()).add(1).day();
      var newDay = new  ConferenceDay();
      newDay.set({date_formatted: newDate});

      this.collection.add(newDay)
      newDay.save({
        success: function(){
          alert('yes')
        },
        error: function(){
          alert('no')
        }
      });
    },
    deleteDay: function(event){
      var id = $('.day-link:last-child').data("id");
      $('.day-link:last-child').remove();
    },
    prevDay: function() {

    },
    nextDay: function() {

    },
    loadTimes: function(){
      var html = time.get('times');
      $('.time_td').append(html);
    }

  });
 var headerView = new HeaderView({ model: header });


        ConferenceView = Backbone.View.extend({
  el: $(".calendar"),
  template: _.template($('#calendar').html()),
  events: {

    },
    initialize: function(){

      //this.listTracks();
      this.collection = new Calendar();
      this.collection.fetch();
      this.collection.bind("reset", this.render, this);
    },
    render: function(){
      var JSONdata = this.collection.toJSON();
      this.$el.html(this.template({days: JSONdata}));
    },

    listTracks: function() {
    }

  });
 var conferenceView = new ConferenceView({model:conferenceDay});

My current routing

 var AppRouter = Backbone.Router.extend({
  routes: {
  '' : 'index',
  'day/:id' : 'changeDay'
  },

  initialize: function() {
  },

  index: function() {

  },
  changeDay: function(id){
    alert("changed");
    this.calender.changeDay(id);
    this.dayView = new ConferenceView({model:conferenceDay});
    $('#calender').html(this.dayView.render().el).text('test');
  },
});
 var app = {
 init: function() {
  var routes = new AppRouter();
  Backbone.history.start({pushState: true});
  }
}
 app.init();

Ideally, I would like the user to click the day-link button and have the url update via push state to the day/:id and then the #calender template would update with the correct model info received from the day update.


Solution

  • There's a lot of code in your post, so I'm not 100% sure the below will cover everything you need to do, but it's a start

    This event handler might be causing some problems:

    changeDay: function(e){
      AppRouter.history.navigate($(this).attr('href'));
      return false;
    }
    

    On a detail level, couple of things are off here:

    1. You don't need to reference history. I'm not sure that the router even has such property. You should call AppRouter.navigate instead.
    2. If you want the router to trigger your changeDay route method, you need to pass an option trigger:true, like so:

      AppRouter.navigate($(this).attr('href'), {trigger:true}).
      

    However, the actual solution is still simpler than that. You can remove the HeaderView.changeDay event handler, and the click a.day-link event binding from the events hash entirely. Backbone Router will detect the changed URL, and call the router method which matches the new URL automatically.