Search code examples
backbone.jsbackbone-viewsbackbone-model

retrieve nested attributes in model


For the life of me, I can't figure out how to get a few attributes in my model.

I define my reportUrl model like this:

    var ReportUrl = Backbone.Model.extend({
        urlRoot: '/api/report/test/'
});

then in my view, I fetch it like this, and add it to my test model. Note - it only fetches one URL for each test:

            var reportUrl = new ReportUrl({ id: test.id });
            reportUrl.fetch();
            test.set({
                reportUrl: reportUrl
            });
                var view = new reportUrlView({
                    model: test
                });

If I write it out, I can see it in my browser console(see the screenshot below). I just can't figure out how to access the data I need.

I need to get the serverUrl and reportExt attributes.

So I define 'this.reportUrl' like this: this.reportUrl = this.model.get('reportUrl');

if I do

console.log('this.reportUrl:', this.reportUrl); 

I see this screen: enter image description here

But I've failed at all my attempts to get the attributes I need:

this.reportUrl.get('serverUrl') = undefined
this.reportUrl.serverUrl = undefined

this.model.attributes.reportUrl.get('serverUrl') = undefined
this.model.attributes.reportUrl.serverUrl = undefined
this.model.attributes.reportUrl.attributes.serverUrl = undfined

this is the only line that produced anything:

this.model.attributes.reportUrl.attributes = id: xxxxxx ^^ the test.id above when I called new ReportUrl.

So is there anyway to access these attributes?

Thanks!


Solution

  • Your major issue is that fetch() is executed asynchronously.

    what you see in console is the data after the request is complete, but your code executes before, hence returning undefined.

    Your code should be

    var reportUrl = new ReportUrl({ id: test.id });
    reportUrl.fetch({
        success:function(model,response){
          test.set({
             reportUrl: model
          });
          var view = new reportUrlView({
             model: test
          });
       }
    });
    

    or

    var reportUrl = new ReportUrl({ id: test.id });
    reportUrl.fetch().then(function(){
      test.set({
         reportUrl: reportUrl
      });
      var view = new reportUrlView({
         model: test
      });
    });
    

    Not sure why you're setting a model into another - It looks like all you need is to do test.fetch(), and your backend shold return an object reportUrl with the required data in response. That'll be much cleaner.

    anyway you can access the attributes like this.model.get('reportUrl').get('serverUrl') , assuming this points to your view.

    this.model.attributes.reportUrl.attributes.serverUrl, this.model.get('reportUrl').attributes.serverUrl, this.model.attributes.reportUrl.get('serverUrl') etc should also work, but that's not the backbone way of doing it.