Nicolas
Nicolas

Reputation: 1848

backbone.js 'undefined' get request

This is my code:

$(function (){
var Slide = Backbone.Model.extend({
    defaults: {
        castid  :1,
        id      :1
    },
    urlRoot:  function(){
        return 'slidecasts/' + this.get("castid") + '/slides/';
    },
});


var SlideView = Backbone.View.extend({
    el: $("#presentation"),
    events: {
        'click #next': 'next',
        'click #previous': 'previous',
    },
    initialize: function(){
        _.bindAll(this, 'render', 'next');
        this.model.bind('change', this.render);
        this.render();
    },
    render: function(){
        this.model.fetch();
        var variables = { 
            presentation_name: "This is a Slide-Number: ",
            slidenumber: "xxx",
            imageurl:  this.model.url() +"/"+ this.model.get('imageLinks'), 
            slide_content:  this.model.get("content")};
        var template = _.template( $("#slide_template").html(), variables );
        this.$el.html( template );
        return this;
    },
    next: function(){
        console.log(this.model.id);
        this.model.nextslide();
    },
    previous: function(){
        console.log("previous function in view");
    }
});

testslide = new Slide();
var slideView = new SlideView({model: testslide});

});

This works fine but in the debug console I always see a GET Request to "slidecasts/1/slides/1/undefined" which of course fails. I don't really understand where I trigger this get request.

Edit - the template code

<script type="text/template" id="slide_template">
  <label>Presentation <%= presentation_name %>  </label> <br/>
  <img src="<%= imageurl %>" id="slide_pic" /> <br/>
  <textarea id="slide_content">
    <%= slide_content %>
  </textarea>
  <div id="next">next slide </div>
  <div id="previous">previous slide </div>  
</script>

Upvotes: 1

Views: 564

Answers (2)

mu is too short
mu is too short

Reputation: 434616

You have an asynchronous problem.

This is the sequence of events:

  1. You call this.model.fetch() to populate the model.
  2. You say variables.imageurl = this.model.url() + '/' + this.model.get('imageLinks').
  3. The (asynchronous) fetch hasn't returned yet so this.model.get('imageLinks') is undefined.
  4. You build the HTML and use this.$el.html(template) to update the page.
  5. The browser renders your HTML using the incorrect imageurl from 2.
  6. A bad GET request is logged because of 5.
  7. The fetch from 1 returns from the server and triggers a 'change' event.
  8. The 'change' event triggers a new call to render.
  9. This render call has a fully populated this.model so variables.imageurl is correct and the HTML comes out right this time.

If you let the fetch trigger the render then the problem will go away:

initialize: function(){
    _.bindAll(this, 'render', 'next');
    this.model.bind('change', this.render);
    this.model.fetch();
},
render: function() {
    // As before except no this.model.fetch()
}

Upvotes: 4

fguillen
fguillen

Reputation: 38772

How I can't see the template you are using I'm just guessing here:

The problem is in this line:

this.model.url() +"/"+ this.model.get('imageLinks'), 

Your template is trying to define an <img> element with such URL but the imageLinks attribute is undefined.

Upvotes: 1

Related Questions