简体   繁体   中英

Ajax call to GitHub API from Backbone

I am exploring Backbone, and have run into a problem trying to retrieve JSON from the GitHub API . I am creating a quick web app to retrieve a paginated list of open issues from the GitHub Rails repo. Where I am hung up is on the call to retrieve the JSON containing the first page of issues (forget pagination for the moment).

I can get that first page of issues with a simple jQuery Ajax call, but that isn't properly using Backbone.

$.getJSON("https://api.github.com/repos/rails/rails/issues?state=open", function(data) {...});

Here is my Backbone JavaScript -- it's easier to deal with all in one file at this point.

$(function() {
    // Define namespace as RailsIssues
    window.RailsIssues = {
        Models: {},
        Collections: {},
        Views: {}
    };

    // Global function to simplify template property syntax
    window.template = function(id){
        return _.template( $('#' + id).html());
    }

    // Issue model
    RailsIssues.Models.Issue = Backbone.Model.extend({
    });

    // IssueList collection
    RailsIssues.Collections.Issues = Backbone.Collection.extend({
        model: RailsIssues.Models.Issue,

        /* not getting anything back */
        url: "https://api.github.com/repos/rails/rails/issues",

        parse: function(data){
            return data;
        }
    });

    // Issue view
    RailsIssues.Views.Issue = Backbone.View.extend({
        tagname: 'li',
        template: template('issueTemplate'),
        initialize: function(){
            this.render();
        },
        render: function(){
            this.$el.html(this.template(this.model.toJSON()));
            return this;
        }
    });

    // Issues view
    RailsIssues.Views.Issues = Backbone.View.extend({
        template: template('issuesTemplate'),
        render: function(eventName) {
            _.each(this.model, function(issue) {
                var number = issue.attributes['number'];
                //var title = issue.attributes['title'];
                var xtemplate = this.template(issue.toJSON());
                $(this.el).append(xtemplate);
                }, this);

            return this;
        }
    });

    Backbone.sync = function(method, model) {
        alert(method + ": " + model.url);
    }

    var issuesView = new RailsIssues.Views.Issues({ collection: RailsIssues.Views.Issues });
    $(document.body).append(issuesView.render().el);
});

And here is my HTML -- there is really nothing of interest here except the resources. I am just trying to get the data and shove it into the document body at this point -- styling will come later.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script id="issuesTemplate" type="text/template">
          <li><%= number %></li>
      </script>
      <script src="script/underscore.js"></script>
      <script src="script/jquery-1.11.1.min.js"></script>
      <script src="script/backbone.js"></script>
          <script src="script/script.js"></script>
        <title>Rails Issues</title>
    </head>
    <body>
        <header>
            Open Issues in Rails GitHub
        </header>
    </body>
</html>

What am I missing in trying to retrieve the JSON data? The code just fails silently, returning nothing, whereas my jQuery above does return the desired JSON. Anything you can suggest would be really helpful.

I never was able to figure out my error on the code as shown in my question, but with the help of this excellent tutorial , I was at last able to get the Ajax API call working.

This code merely retrieves the first page of results (issues posted on the Rails GitHub page ) and displays the issue number in an unordered list.

Here is the HTML which includes the templates and script tags in the proper sequence:

<!DOCTYPE html lang="en">
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="icon" type="image/x-icon" href="https://assets-cdn.github.com/favicon.ico">      

         <script id="issuesTemplate" type="text/template">
            <% $.each(issues, function() { %>
                <li><%= this.number %></li>
            <% }); %>          
        </script>       

        <script src="script/underscore.js"></script>
        <script src="script/jquery-1.11.1.min.js"></script>
        <script src="script/backbone.js"></script>
        <script src="script/script.js"></script>
        <title>Rails Issues</title>   
    </head>
    <body>
        <header>
            Open Issues in Rails GitHub
        </header>
        <div class="theList">Loading... Please Wait.</div>
    </body>
</html>  

And here is the script.js file

var RI = {
    run: function() {
        this.listview = new this.listView();
        this.issuescollection = new RI.issuesCollection();
        this.router = new this.Router();
        Backbone.history.start();
        this.router.navigate('list_issues');
    }
};

RI.Router = Backbone.Router.extend({
    routes: {
        'list_issues': 'renderListIssuesPage'
    },

    renderListIssuesPage: function () {
        RI.listview.setElement('div.theList');
        RI.listview.listIssuesPage();
    }
});

RI.issueModel = Backbone.Model.extend({

});

RI.issuesCollection = Backbone.Collection.extend({
    model: RI.issueModel,   
    url: 'https://api.github.com/repos/rails/rails/issues'
}); 

RI.listView = Backbone.View.extend({
    el: 'div.theList',

    template: _.template($('#issuesTemplate').html()),

    initialize: function () {
        _.bindAll(this, 'listIssuesPage', 'render');
    },

    render: function (response) {
        var self = this;

        this.$el.html(this.template({issues: response}));
    },

    listIssuesPage: function (querystring) {
        var self = this;

        RI.issuescollection.fetch({
            data: querystring,
            success: function(collection, response) {
                self.render(response);
            }
        });
    }
});

$(function() {
    RI.run();
}); 

I tried to run your code, but was missing the issuesTemplate and issueTemplate , however I noticed that you instantiate the view, but never the collection or model. Instead you've pointed the view's collection to the definition of the views issues (but not the collection instance):

var issuesView = new RailsIssues.Views.Issues({ collection: RailsIssues.Views.Issues });

Also, once you create the new collection you'll need to call fetch() to make Backbone perform the API call to gather the needed JSON. What I would recommend is to do something like the following:

var issuesCollection = new RailsIssues.Collections.Issues();
issuesCollection.fetch();  // makes the GET request
var issuesView = new RailsIssues.Views.Issues({ collection: issuesCollection });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM