2

I am evaluating the Backbone-Relational plugin for modeling a tree. I have the following sample code

var SurveyTreeNode = Backbone.RelationalModel.extend({
    relations: [{
        type: Backbone.HasMany,
        key: 'questions',
        relatedModel: 'SurveyTreeNode'
    }]
});


var survey = {
    id: 1,
    questions: [
        { 
            id: 2, 
            text: 'What is your name?' 
        },
        { 
            id: 3, 
            text: 'What hours do you work?', 
            questions: [
                {
                    id: 3,
                    text: 'On Monday?'
                },
                {
                    id: 4,
                    text: 'On Tuesday?'
                }
            ]                
        }
    ]
};

var questionTree = new SurveyTreeNode(survey);

which yields (in Google Chrome console):

no model, key or relatedModel (function (){ parent.apply(this, arguments); }, "questions", undefined) 

I've loaded this code into a jsfiddle, as the error doesn't display exactly as above (shows a child element that can be expanded): http://jsfiddle.net/hoffmanc/XsDQu/

hoffmanc
  • 614
  • 9
  • 16

2 Answers2

4

Backbone Relational expects to be able to find the constructors for related models in the global scope, at the path given in the relatedModel property.

The issue is that its not finding the constructor function for SurveyTreeNode

I'm not sure how you're executing the above code in your local environment, or exactly what jsFiddle does to wrap code (probably wrapping it in some DOMReady event), but in both cases, SurveyTreeNode is not in the global scope.

If you remove the var keyword before SurveyTreeNode, it will be available in the global scope and the subsequent code works.

See this jsFiddle: http://jsfiddle.net/edwardmsmith/qTA83/

Edward M Smith
  • 10,627
  • 2
  • 46
  • 50
  • Ye typical rtfm question :D "relatedModel: Required. A string that can be resolved to an object on the global scope, or a reference to a Backbone.RelationalModel." – inf3rno May 22 '13 at 09:41
1

Another workaround if you don't want to pollute global namespace:

var MenuNode = function () {
    Backbone.RelationalModel.apply(this, arguments);
};
MenuNode = Backbone.RelationalModel.extend({
    constructor: MenuNode,
    relations: [
        {
            type: Backbone.HasMany,
            key: "children",
            relatedModel: MenuNode,
            reverseRelation: {
                key: "parent"
            }
        }
    ]
});

I suggested to add a Backbone.selfRelated (or something similar) flag to avoid hacking like this. https://github.com/PaulUithol/Backbone-relational/issues/347

inf3rno
  • 24,976
  • 11
  • 115
  • 197