简体   繁体   中英

Getting a json from collection to view in backbone.js

I am new to backbone.js and is having some problem with my app. I have a collection which relies on a json data source. I am able to console.log the json in my parse method. Is that enough to bind the collection to my view? I don't understand the use of fetch method.

My collection looks like as follows,

(function (collections,model) {
collections.Directory = Backbone.Collection.extend({
        initialize : function(){
            console.log('we are here');
            },
        model:model.item,
        url:'collections/json/data.json',
        parse:function(response){
                console.log(response);
                return response;
            }
    });
})(app.collections,app.models);

And my master view looks like this,

(function(views,collections){

views.masterView = Backbone.View.extend({
         el : $("#contacts"),
        initialize : function(){
            console.log('view initialize inside render');
            this.render();
            this.$el.find("#filter").append(this.createSelect());
            this.on("change:filterType", this.filterByType, this);
            this.collection.on("reset", this.render, this);
            this.collection.on("add", this.renderContact, this);
            //console.log('we are here'+app.collections.CollectionItems.fetch());
            console.log('view initialize');
        },

        render : function(){

            this.$el.find("article").remove();
            _.each(this.collection.models,function(item){

                this.renderContact(item);
               },this);

            },
             renderContact: function (item) {
            views.contactView = new app.views.ContactView({
                model: item
            });
            this.$el.append(contactView.render().el);
        },
            getTypes : function () {
            return _.uniq(this.collection.pluck("Qno"));
        },
    createSelect : function () {

        var select = $("<select/>", {
                    html: "<option value='all'>All</option>"
                });
    _.each(this.getTypes(), function (item) {
        var option = $("<option/>", {
            value: item.toLowerCase(),
            text: item.toLowerCase()
        }).appendTo(select);
    });
    return select;
    },
     events: {
            "change #filter select": "setFilter",
            "click #add": "addContact",
            "click #showForm": "showForm"
        },
    setFilter : function(e){
        this.filterType = e.currentTarget.value;
        this.trigger("change:filterType");

    },
    filterByType: function () {
    if (this.filterType === "all") {
        this.collection.reset(contacts);
        routerURL.navigate("filter/all");
    } else {
        this.collection.reset(contacts, { silent: true });
        var filterType = this.filterType,
            filtered = _.filter(this.collection.models, function (item) {
            return item.get("type").toLowerCase() === filterType;
        });
        this.collection.reset(filtered);
        routerURL.navigate("filter/"+filterType);
    }
},
    addContact : function(e){
        e.preventDefault();
        var contModel = {};
        $("#addContact").children("input").each(function(i, el){
            if($(el).val() !== "")
                contModel[el.id] = $(el).val();

        });
        contacts.push(contModel);
        if (_.indexOf(this.getTypes(), contModel.type) === -1) {
                this.collection.add(new Contact(contModel));
                this.$el.find("#filter").find("select").remove().end().append(this.createSelect());
            } else {
                this.collection.add(new Contact(contModel));
            }
    },
    showForm : function(){
        this.$el.find("#addContact").slideToggle();   
    }

        });
      })(app.views,app.collections);

my model is very simple and looks like this,

(function ( models ) {
    models.Item = Backbone.Model.extend({
        defaults :{Qno:'1',Desc:'hello'}
        });
})( app.models );

ihave one js file instantiatin viewsand collections

    (function () {

        window.app = {};
        app.collections = {};
        app.models = {};
        app.views = {};
        app.mixins = {};

       $(function(){
                app.collections.CollectionItems = new app.collections.Directory();
                //app.collections.CollectionItems.fetch();
                //console.log(app.collections.CollectionItems.fetch());

                app.collections.CollectionItems.fetch({
                    success: function (collection,response) {
                        console.log(response);
                    }
                });
                //console.log(app.collections.CollectionItems.toJSON());
                console.log('coll started');
                app.views.app = new app.views.masterView({collection: app.collections.CollectionItems});
                console.log('view is jus about fine!!');
                //app.views.pagination = new app.views.PaginatedView({collection:app.collections.paginatedItems});
        });






    var ContactsRouter = Backbone.Router.extend({
    routes: {
        "filter/:type": "urlFilter"
    },
    urlFilter: function (type) {
        master.filterType = type;
        master.trigger("change:filterType");
    }
});

    var routerURL = new ContactsRouter();

    Backbone.history.start();
})();

my landing page looks like this with a template in it

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Backbone.js Web App</title>
        <link rel="stylesheet" href="css/screen.css" />
    </head>
    <body>

        <div id="contacts">

</div>

        <script id="contactTemplate" type="text/template">

            <h1><%= Qno %></h1>

        </script>
        <script src="js/jquery.js"></script>
        <script src="js/underscore-min.js"></script>
        <script src="js/backbone-min.js"></script>
        <script src="app.js"></script>
        <script src="collections/Directory.js"></script>
        <script src="models/item.js"></script>
        <script src="views/masterView.js"></script>
         <script src="views/simpleView.js"></script>
        <!--<script src="js/backbone.paginator.js"></script>-->
    </body>
</html>

I just can't get my head around this. The view is not rendered with the collection data. Please help!

I think it's because the fetch method on your collection is executed asynchronously and has therefore not completed when you create your view (if you look at the console I would expect the log statement in the success callback to display after the log statements underneath). This means that your view render method is called before the collection is populated and the reset event (which you're binding to in your view) is never triggered.

Try updating the code which instantiates everything as follows:

   $(function(){
            app.collections.CollectionItems = new app.collections.Directory();
            //app.collections.CollectionItems.fetch();
            //console.log(app.collections.CollectionItems.fetch());

            app.collections.CollectionItems.fetch({
                success: function (collection,response) {
                    console.log(response);
                    app.views.app = new app.views.masterView({collection: app.collections.CollectionItems});
                }
            });
    });

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