简体   繁体   中英

backbone.js collection usage

I'm running into a problem maintaining my collection. First, I load attendees into a collection via fetch. This loads existing attendees from the database in to the collection. I also have a button which allows a user to add new attendees. When an attendee is manually entered it seems to wipe out the models loaded into the collection via fetch and starts fresh. All manually added attendees now populate the collection; however, i would like both the fetch loaded and manually added attendees to populate this list.

var InviteeView = Backbone.View.extend({
tagName: "tr",
initialize: function() {
    this.collection = new InviteeJSONList();    
    _.bindAll(this, 'render','appendItem','remove','saveInvitee');
},
events: {
    "click .removeInvitee":"remove",
    "click .saveInvitee":"saveInvitee"
},
render: function() {
    var source = $("#invitee-template").html();
    var template = Handlebars.compile(source);
    var context = inviteeListJSON.attributes['json'];
    var html=template(context);

    $(this.el).html(html);

    return this;
},
appendItem: function() {
    $("#attendees").append(this.render().el);
},
remove: function() {
    $(this.el).remove();
},
saveInvitee: function() {
    var value = $(this.el).find('select').val();
    var model = this.collection.attributes['json']['invitees'];
    model = model.filter(function(attributes) {return attributes.encrypted_id==value});
    var attendee = new Attendee({
        user_id: model[0]['id'],
        meeting_id: '<?=$mid?>',
        status: 'Uncomfirmed',
        first_name: model[0]['first_name'],
        last_name: model[0]['last_name'],
        email: model[0]['email'],
        user_uuid: model[0]['encrypted_id'],
        unavailable_dates: model[0]['unavailable_dates']
    });

    attendeeView.addAttendeeItem(attendee.attributes)
    this.remove();
}
});

var AttendeeList = Backbone.Collection.extend({
model: Attendee,
url: '<?=$baseURL?>api/index.php/attendees/<?=$mid?>&timestamp=<?=$timestamp?>&userid=<?=$userid?>&apikey=<?=$apikey?>',
parse: function(response) {
    if(response!="No History") {
        $.each(response['attendees'], function(key, value) {
            attendeeView.addAttendeeItem(value);
        });
        $('.loading_attendees').hide();
    }
    else {
        $('.loading_attendees').html("No attendees exists for this meeting.");
    }
}
});

var AttendeeView = Backbone.View.extend({
el: $('body'),
initialize: function() {
    _.bindAll(this, 'render','fetchAttendees', 'appendItem', 'addAttendeeItem');
    this.counter=0;
    this.collection = new AttendeeList();
    this.collection.bind('add', this.appendItem);
    this.fetchAttendees();
},
events: {
    "click #addInvitee":"appendInvitees",
},
appendInvitees: function() {
    var inviteeView = new InviteeView();
    inviteeView.appendItem();
},
render: function() {

},
fetchAttendees: function() {
    this.collection.fetch({
        success: function(model, response) {

        },
        error: function(model, response) {
            $('#loading_attendees').html("An error has occurred.");
        }
    });
},
appendItem: function(item) {
    var attendeeItemView = new AttendeeItemView({
        model: item
    });
    $("#attendees").append(attendeeItemView.render().el);
    attendeeItemView.updateAttendeeStatusSelect();

},
addAttendeeItem: function(data) {
    this.counter++;
    var attendee = new Attendee({
        id: data['id'],
        user_id: data['user_id'],
        meeting_id: data['id'],
        status: data['status'],
        comments: data['comments'],
        attended: data['datetime'],
        first_name: data['first_name'],
        last_name: data['last_name'],
        email: data['email'],
        counter: this.counter,
        user_uuid: data['user_uuid'],
        unavailable_dates: data['unavailable_dates']
    });

    this.collection.add(attendee);
},
});

After the collection (2 items loaded from REST API) is loaded via fetch():

console.log(this.collection.models) outputs:
[d]
[d,d] 

Then when I manually add an attendee via a button the collection seems to reset:

console.log(this.collection.models) outputs:
[d] 

Good that it's working, as there are many ways to go. I probably would have structured it a bit differently to leverage the Backbone methods that instantiate modes, but working code is the real goal, so these are just my thoughts:

  • Rather than actually instantiate the Models in the Collection parse() method, merely have parse return an array of data objects from which Backbone would instantiate the models, and trigger a

  • Rather than call fetch for the Collection inside AttendeeView, but outside the View class

  • Either have AttendeeView represent the view for a single attendee, or name it AttendeeListView and have it render the list

For instance:

AttendeeList = Backbone.Collection.extend({
 ...
   parse: function(response) {
           // create an array of objects from which the models can be parsed
           var rawItems = [];
               $.each(response['attendees'], function(key, value) {
                 rawItems.push({
                        id: data['id'],
                        user_id: data['user_id'],
                        meeting_id: data['id'],
                        status: data['status'],
                        comments: data['comments'],
                        attended: data['datetime'],
                        first_name: data['first_name'],
                        last_name: data['last_name'],
                        email: data['email'],
                        counter: this.counter,
                        user_uuid: data['user_uuid'],
                        unavailable_dates: data['unavailable_dates']
                    });
                });
              return rawItems;
           },
         ...
       }

and then either use the success/failure call backs:

  AttendeeList.fetch( onListFetchSuccess , onListFetchFail );

or listen for the reset event that gets triggered:

  AttendeeList.on('reset', createAttendeeListView );

(I didn't actually edit and run the code, this is just an outline)

I ended up resolving the issue by removing the url parameter and parse function out of the collection and into the view. Now everything works as expected.

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