Backbone insert an App inside an App

让人想犯罪 __ 提交于 2019-12-12 15:13:00

问题


I have an app in backbone where I get data from a server and return me data about hotel. Each hotel can contain many rooms (Single, double, triple..). For this I have create two json hotel.json:

[
  {
    "id": "1", 
    "name": "Hotel1"
  }, 
  {
    "id": "2", 
    "name": "Hotel2"
  }, 
  {
    "id": "3", 
    "name": "Hotel3"
  }
]

rooms.json

[
    {
      "room" : [
        {
          "id" : "r1",
          "hotel_id" : "1",
          "name" : "Singola",
        }
      ]
    },
    {
      "room" : [
        {
          "id" : "r1_1",
          "hotel_id" : "1",
          "name" : "Doppia",
        }
      ]
    },
    {
      "room" : [
        {
          "id" : "r2",
          "hotel_id" : "2",
          "name" : "Singola",
        }
      ]
    },
    {
      "room" : [
        {
          "id" : "r2_1",
          "hotel_id" : "2",
          "name" : "Tripla",
        }
      ]
    },
  ]

In rooms.json there is a field called hotel_id to link rooms to its hotel. Well this is my app in backbone to view hotel:

var Hotel = Backbone.Model.extend({
            defaults: function() {
                return {
                    name: 'HOTEL NAME',
                    star: '5'
                }
            }
        });

        var HotelsCollection = Backbone.Collection.extend({
            model: Hotel,
            url: "includes/test-data.json",

            initialize: function(){
                console.log("Collection Hotel initialize");
            },

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

        var HotelView = Backbone.View.extend({ 
            template: _.template($("#hotel-list-template").html()),
            initialize: function(){ 
                this.collection = new HotelsCollection();
                this.collection.bind('sync', this.render, this);
                this.collection.fetch();
            },
            render: function(){
                console.log('Data hotel is fetched');
                var element = this.$el;
                element.html('');

                $(this.el).html(this.template({hotel: this.collection.models}));
            } 
        });

This is my template in uderscore:

<script type="text/template" id="hotel-list-template">
    <% _.each(hotel, function(name) { %> 
    <div id="hotel-container-<%= name.attributes.id %>">
        <p>Nome Hotel: <%= name.attributes.name %></p>
    </div>
    <% }); %>
    </script>

Now, how can I insert each room inside its hotel in the same div? I thinked to make a classic model, a collection that fetch data but in the view in the render how can I tell to backbone to insert only room with hotel_id=1 to the div with id=hotel-container-1?

------------------UPDATE---------------------

var Hotel = Backbone.Model.extend({
            defaults: function() {
                return {
                    name: 'HOTEL NAME',
                    star: '5'
                }
            }
        });

        var HotelsCollection = Backbone.Collection.extend({
            model: Hotel,
            url: "includes/test-data.json",

            initialize: function(){
                console.log("Collection Hotel initialize");
            },

            parse: function(response){
                return(response);
            },
            getRooms : function() {
                return _.map(allRooms.where({"hotel_id" : this.get("id")}), function(room) {
                    return room.toJSON();
                });
            },
            addRoom : function(room) {
                room.set("hotel_id", this.get("id"));
                allRooms.add(room);
            },
            // this will return Backbone´s native toJSON Object
            // with an extra field "rooms" which you can access
            toJSON : function() {
                var parent = Backbone.Collection.prototype.toJSON.call(this);
                return _.extend({}, parent, {rooms : this.getRooms().toJSON()});
            }
        });

        var HotelView = Backbone.View.extend({ 
            template: _.template($("#hotel-list-template").html()),
            initialize: function(){ 
                this.collection = new HotelsCollection();
                this.collection.bind('sync', this.render, this);
                this.collection.fetch();
            },
            render: function(){
                console.log('Data hotel is fetched');
                var viewModel = this.collection.toJSON();
                this.$el.html(this.template({models:viewModel}));

            } 
        }); 


var Room = Backbone.Model.extend();
var Rooms = Backbone.Collection.extend({model:Room});

var allRooms = new Rooms();

        var hotelView = new HotelView({ 
            el: $("#hotel") 
        });

回答1:


I advise We add some changes to project architecture. Firstly We need to change hotel model like this:

{
    "id": "1", 
    "name": "Hotel1",
    "rooms": []
} 

Secondly Model and Collection :

var Room = Backbone.Model.extend();
var Rooms = Backbone.Collection.extend({
    model:Room,
    url : "rooms.json"
});
var Hotel = Backbone.Model.extend({});
var HotelCollection = Backbone.Collection.extend({
    model: Hotel,
    url: "includes/test-data.json",
    initialize: function(){
        console.log("Collection Hotel initialize");
    },

    parse: function(response) {
       response.rooms = new Rooms(response.rooms);
       return response;
    }    
});

Third View :

    var HotelView = Backbone.View.extend({ 
        template: _.template($("#hotel-list-template").html()),
        initialize: function(){ 
            this.collection = new HotelCollection();
            this.collection.bind('sync', this.render, this);
            this.collection.fetch();
        },
        render: function(){
            console.log('Data hotel is fetched');
            bindRoomToHotel();
            var element = this.$el;
            element.html('');

            $(this.el).html(this.template({hotel: this.collection.models}));
        },

        bindRoomToHotel: function() {
            allRooms = new Rooms();
            allRooms.fetch();
            _.each(this.collection.models, function(hotel) {
                 rooms = allRooms.where({'hotel_id' : hotel.id});
                 //
                 currentHotelRooms = hotel.get('rooms');
                 currentHotelRooms.add(rooms);
                 // or You can write like 
                 // hotel.get('rooms').add(rooms);
            }
        } 
    });
    var hotelView = new HotelView({ 
        el: $("#hotel") 
    });

I guess it is all. I hope it help You




回答2:


first of all you are missing a Room Model and a Room Collection Then, you should have an instance somewhere of all your Rooms.

var Room = Backbone.Model.extend();
var Rooms = Backbone.Collection.extend({
    model:Room,
    url : "rooms.json"
});

var allRooms = new Rooms();

quite simple until here.

no you would create some methods for your hotel model, which would you enable some actions for your rooms

var Hotel = Backbone.Model.extend({
    getRooms : function() {
        return _.map(allRooms.where({"hotel_id" : this.get("id")}), function(room) {
            return room.toJSON();
        });
    },
    addRoom : function(room) {
        room.set("hotel_id", this.get("id"));
        allRooms.add(room);
    },
    // this will return Backbone´s native toJSON Object
    // with an extra field "rooms" which you can access
    toJSON : function() {
        var parent = Backbone.Model.prototype.toJSON.call(this);
        return _.extend({}, parent, {rooms : this.getRooms().toJSON()});
    }
});
var HotelsCollection = Backbone.Collection.extend({
    model: Hotel,
    url: "includes/test-data.json",
    initialize: function(){
        console.log("Collection Hotel initialize");
    },
    parse: function(response){
        return(response);
    }

});

this is just a sample, you can do much more out of this.

now in your render function....

you can put anything to the underscores render method.

for example :

render : function() {
    //this will give you a nice formatted array (see toJSON override above)
    var viewModel = this.collection.toJSON();
    this.$el.html(this.template({models:viewModel});
}

In your View now, you have access to your "rooms" array...

<script type="text/template" id="hotel-list-template">
    <% _.each(models, function(hotel) { %> 
    <div id="hotel-container-<%= hotel.id %>">
        <p>Nome Hotel: <%= hotel.name %></p>
        <ul>
        <% _.each(hote.rooms, function(room) { %>
            <li><%=room.name%></li>
        <% }); %>
        </ul>
    </div>
    <% }); %>
</script>



回答3:


You could create a Room model, then a Rooms collection. Then you add rooms as property of HotelView. Then you call a fetch and use filter:

    var HotelView = Backbone.View.extend({ 
        template: _.template($("#hotel-list-template").html()),
        initialize: function(){ 
            this.collection = new HotelsCollection();
            this.collection.bind('sync', this.render, this);
            this.collection.fetch();

            this.rooms = new RoomsCollection();
            this.rooms.fetch();

            var self = this;
            this.rooms = this.rooms.filter(function(room){
                      return room.get("hotel_id") === self.get("id");
                })
         },

Then you just have to add the rooms to the div. You can create view for the rooms if your app is complex.

Here are the docs of the filter function.

Edit: you create a template for one room. Then in the hotel template you put a empty div with #rooms id. Then for each room you append the template in this div.



来源:https://stackoverflow.com/questions/17394461/backbone-insert-an-app-inside-an-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!