Search code examples
javascriptjquerybackbone.js

Backbone.js primer customisation issues


I've been trying to get my first Backbone.js app up and running, following the Backbone.js primer here.

I've followed the example through and now I'm trying to customise it for my purposes which are to simply retrieve and read a JSON file from my server. I don't need to be able to change or delete any of the data.

I've set up my html as per the primer below:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Backbone.js Primer</title>

  <script type="text/javascript" src="./node_modules/jquery/dist/jquery.min.js"></script>
  <script type="text/javascript" src="./node_modules/underscore/underscore-min.js"></script>
  <script type="text/javascript" src="./node_modules/backbone/backbone-min.js"></script>
  <script type="text/javascript" src="./node_modules/moment/moment.js"></script>
  <script type="text/javascript" src="./backbone.js"></script>
</head>

<body>
  <div>
      <h1>Transcripts Data</h1>

      <div id="dailyTranscripts-app">
        <ul class="dailyTranscripts-list"></ul>
      </div>
  </div>

</body>

</html>

I've then coded my backbone.js file as the primer describes below:

var yesterday = moment (new Date()).add(-1, 'days').format('YYYY-MM-DD')
var yesterdaysDataURL = 'https://mihndbotblob.blob.core.windows.net/mihndbot-transcripts/finalTranscripts/dailyTranscripts/' + yesterday + '.json'

// Model class for each transcript iten
var DailyTranscriptsModel = Backbone.Model.extend({
  defaults: {
    type: null,
    MessageID: null,
    MessageTime: null,
    MessageChannel: null,
    MessageSenderID: null,
    MessageSenderName: null,
    ConversationID: null,
    MessageText: null,
    MessageRecipientID: null,
    QuickReplyDisplayText: null,
    QuickReplyPayload: null,
    Question: null,
    Answer: null,
    FollowUpPrompts: null
  }
});

// Collection class for the DailyTransctipts list endpoint
var DailyTranscriptsCollection = Backbone.Collection.extend({
  model: DailyTranscriptsModel,
  url: yesterdaysDataURL
});

// View class for displaying each dailyTranscripts list item
var DailyTranscriptsListItemView = Backbone.View.extend({
  tagName: 'li',
  className: 'dailyTranscripts',

  initialize: function () {
    this.listenTo(this.model)
  },

  render: function () {
    var html = '<b>Message ID: </b> ' + this.model.get('MessageID');
    html += '<br><b>Message Time: </b>' + this.model.get('MessageTime');
    this.$el.html(html);
    return this;
  }
});

// View class for rendering the list of all dailyTranscripts
var DailyTranscriptsListView = Backbone.View.extend({
  el: '#dailyTranscripts-app',

  initialize: function () {
    this.listenTo(this.collection, 'sync', this.render);
  },

  render: function () {
    var $list = this.$('ul.dailyTranscripts-list').empty();

    this.collection.each(function (model) {
      var item = new DailyTranscriptsListItemView({model: model});
      $list.append(item.render().$el);
    }, this);

    return this;
  }
});

// Create a new list collection, a list view, and then fetch list data:
var dailyTranscriptsList = new DailyTranscriptsCollection();
var dailyTranscriptsView = new DailyTranscriptsListView({collection: dailyTranscriptsList });

dailyTranscriptsList.fetch();

The major changes I've made to the code (apart from some customisations) are to remove the templates the primer uses to create the views (I couldn't get them working) and I've removed the Backbone CRUD elements as I only require my app to read data from the server, not update or delete it.

The issue I have is that whilst I'm pulling back the JSON file from the server, none of the data is rendering in the HTLM <div> as expected, it's just blank.

I know that Backbone.js is retrieving the data as when I add .then(function() {console.log(dailyTranscriptsList);}); to the final dailyTranscriptsList.fetch() call I can see the data in the browser console:

enter image description here


Solution

  • You need to wrap all of your backbone.js code within jQuery's .ready()

    // backbone.js
    
    $(document).ready(function () {
    
      // all your backbone.js code here
    
    })
    

    This causes your js to run after the DOM is ready, so Backbone will know how to find the elements it needs in order for views to work.

    You could also move <script type="text/javascript" src="./backbone.js"></script> to the end of the page, right before </body>