4
votes

I'd appreciate help in understanding why I'm getting an uncaught reference error (see code below). Essentially, upon view initialization I'm fetching a model and within the render method I'm passing "this.model" -- the instance model -- to the template. In all other views, even when the instance model is undefined an uncaught reference error is NOT thrown. Does anyone know why it is thrown here?

Views.Projects.EditView = Backbone.View.extend({

    tagName: 'div',

    id: 'edit-project-content',

    template: JST['projects/edit'],

    initialize: function(){
        this.model = new Models.Project({id: this.options.projectId});
        this.model.bind('change', this.render, this);
        this.model.fetch({
            error: function(model, response) { alert('Error...Please try again.'); }
        });
    },

    render: function() {
        $(this.el).html(this.template({project: this.model})); // Error references this line.
        return this;
    }
});

Template:

<% if (typeof project != 'undefined') { %>
<div id="edit-details">
    <form id="edit-project-form">
        <ul>
            <li>
                <p class='form-title'>Edit Project: "<%= project.get('title') %>"</p>
            </li>
            <li>
                <label for='project-title'>Project Title:</label>
                <input id='project-title' type='text' value="<%= project.get('title') %>" />
            </li>
            <li>
                <label for='due-date'>Due Date:</label>
                <input id='due-date' type='text'></input>
            </li>
            <li>
                <label for='project-description'>Description:</label>
                <textarea id='project-description'><%= project.get('description') %></textarea>
            </li>
            <li>
                <input id='submit-project-edits' type='submit' value='Edit' />
            </li>
        </ul>
    </form>
</div>
<% } %>

Thanks.

3
It is a perfect occasion to use your browser's debugger to see what really happens in that template function. What is in your template exactly? - biziclop
@biziclop: I've added the template to my OP. Using my browser's debugger, I've debugged the template function. The template attempts to get the attributes of the project and when it fails to do so, it throws the exception. - Dan
@muistooshort: The fetched model is already properly formatted as JSON; in any event I tried your suggestion, but unfortunately it didn't work. - Dan
Works for me (jsfiddle.net/ambiguous/SyznD). Could you be calling render before the this.model.fetch() completes? - mu is too short
@muistooshort: I forked your example to make it closer to my code; take a look -- jsfiddle.net/z3hs3 render is called as soon as the view is initialized (and the view initialize function triggers the model to fetch), so I wouldn't be surprised if render is called before fetch is completed. But that shouldn't be an issue, since the template checks for an undefined project/model. - Dan

3 Answers

0
votes

Try this:

render: function() {
    model = this.model;
    $(this.el).html(this.template({project: model})); // Error references this line.
    return this;
}
0
votes

You could change

<% if (typeof project != 'undefined') { %>

to

<% if( project != null ) { %>

or

<% if( project ) { %>

See https://developer.mozilla.org/en/JavaScript/Reference/Operators/typeof

typeof undefined === 'undefined'
typeof null === 'object'

Trying to access a property of a null or undefined will throw an exception in JS. (I miss ActionScript 2 sometimes a bit :)

0
votes

I replicated your code and when I debug it in console, I am getting the following error.

Uncaught TypeError: Object # has no method 'get'

I have seen the "project" model in the console and it is binding the model to the template. This might be a lead on your side, if you could replicate it.

I had the same issue in my application and this is what I have done and it worked. I had to specify the type of model with in the view and it worked. Try that and see if it helps. Hope it helps.

Views.Projects.EditView = Backbone.View.extend({

    tagName: 'div',

    **model : your model**

    id: 'edit-project-content',

    template: JST['projects/edit'],

    initialize: function(){
        this.model = new Models.Project({id: this.options.projectId});
        this.model.bind('change', this.render, this);
        this.model.fetch({
            error: function(model, response) { alert('Error...Please try again.'); }
        });
    },

    render: function() {
        $(this.el).html(this.template({project: this.model})); // Error references this line.
        return this;
    }
});