0

Im using backbone to construct my client-side app, what im trying to do is is display a joke each time the user clicks .get_joke on an event: heres my backbone app code:

JokeModel = Backbone.Model.extend({
   url: '/jokes'
   initialize: function() {
      this.fetch();
  }
});

JokeView = Backbone.View.extend({
    template: _.template("<p><%= joke %></p>")
    events: {
      "click .get_joke" : "render"
  } 
    render: function() {
       var newJoke = new JokeModel;
       $(this.el).html(this.template(newJoke.toJSON()));
  }
});

newJokeView = new JokeView;

the problem when i click .get_joke it deosnt render the joke to the view, i know the the model has been fetched because i check with console.log, but it says joke hasn't been defined, but i dont't know where the problem is. thanks

unknown
  • 846
  • 3
  • 15
  • 38

2 Answers2

3

First of all you can not trust in what console.log sais about a complex object:

What is happening is that the joke.fetch() is asynchronous and when you call jokeView.render() the model is still not ready.

You should modify a little bit your architecture and assigns a proper View to each Joke, so you can have for each Joke a View that is taking care of show it when is needed.

// code simplified an not tested
JokeModel = Backbone.Model.extend({
   url: '/jokes'
});

// This View is new and it is taking care only for the common event "click .get_joke"
// which is not related with any Joke in particular
// This View should be in charge of the JokesCollection 
// but I don't want to make things more complicate
JokeControls = Backbone.View.extend({
  events: {
    "click .get_joke" : "render"
  }, 

  getJoke: function(){
    var joke = new JokeModel();
    var view = new JokeView({ model: joke, el: this.$el.find( ".joke-wrapper" ) });
    joke.fetch();
  },
});


// This is the View that is related with unique Joke
JokeView = Backbone.View.extend({
    template: _.template("<p><%= joke %></p>"),

    initialize: function(){
      // see how it shows itself when the Model is ready
      this.model.on( "change", this.render, this );
    },

    render: function() {
       this.$el.html(this.template(this.model.toJSON()));
    }
});

// Activate the Joke Controls
newJokeControls = new JokeControls({ el: "#joke-controls" });
Community
  • 1
  • 1
fguillen
  • 36,125
  • 23
  • 149
  • 210
0

Try the following:

JokeModel = Backbone.Model.extend({
   url: '/jokes'
   parse : function(data) {
      console.log(data);
      return data;
   }
   initialize: function() {
      this.fetch();
  }
});

I'd also log out the following:

newJoke.toJSON()

To see what you're actually trying to render.

Peeter
  • 9,282
  • 5
  • 36
  • 53