简体   繁体   中英

Getting the attribute from a View's Model when the view is clicked (backbone.js)

When a user clicks on a div with class .photo_container which is part of the view PhotoListView , there is a function sendSelectedPhotoId that will be triggered. This function has to get the attribute photo_id from the Photo model that belongs to this view whose div .photo_container element has been clicked, and send it to the serverside via fetch() .

Problem: So far I managed to get the function sendSelectedPhotoId to be triggered when the div is clicked, but I cant figure out how to get the photo_id attribute of the view's Photo model. How should I achieve this?

On a side note, I'm not sure whether the correct photo_id will be send.

Code

$('#button').click( function() {

    // Retrieve photos
    this.photoList = new PhotoCollection();
    var self = this;
    this.photoList.fetch({
        success: function() {
            self.photoListView = new PhotoListView({ model: self.photoList });
            $('#photo_list').html(self.photoListView.render().el);
        }
    });
});

Model & Collection

// Models
Photo = Backbone.Model.extend({
    defaults: {
        photo_id: ''
    }
});

// Collections
PhotoCollection = Backbone.Collection.extend({
    model: Photo,
    url: 'splash/process_profiling_img'
});

Views

// Views
PhotoListView = Backbone.View.extend({
    tagName: 'div',

    events: {
        'click .photo_container':  'sendSelectedPhotoId'
    },

    initialize: function() {
        this.model.bind('reset', this.render, this);
        this.model.bind('add', function(photo) {
            $(this.el).append(new PhotoListItemView({ model: photo }).render().el);
        }, this);
    },

    render: function() {
        _.each(this.model.models, function(photo) {
            $(this.el).append(new PhotoListItemView({ model: photo }).render().el);
        }, this);
        return this;
    },

    sendSelectedPhotoId: function() {
        var self = this;
        console.log(self.model.get('photo_id'));
        self.model.fetch({
            data: { chosen_photo: self.model.get('photo_id')},
            processData: true,
            success: function() {
        }});
    }

});

PhotoListItemView = Backbone.View.extend({
    tagName: 'div',
    className: 'photo_box',

    template: _.template($('#tpl-PhotoListItemView').html()),


    initialize: function() {
        this.model.bind('change', this.render, this);
        this.model.bind('destroy', this.close, this);
    },

    render: function() {
        $(this.el).html(this.template( this.model.toJSON() ));
        return this;
    },

    close: function() {
        $(this.el).unbind();
        $(this.el).remove();
    }


});

SECOND ATTEMPT

I also tried placing the event handler and sendSelectedPhotoId in the PhotoListItemView where I managed to get the Model's attribute properly, but I can't figure out how to trigger the reset event when the PhotoList collection did a fetch().

View

PhotoListItemView = Backbone.View.extend({
    tagName: 'div',
    className: 'photo_box',

    events: {
        'click .photo_container':  'sendSelectedPhotoId'
    },

    template: _.template($('#tpl-PhotoListItemView').html()),


    initialize: function() {
        this.model.bind('change', this.render, this);
        this.model.bind('destroy', this.close, this);
    },

    render: function() {
        $(this.el).html(this.template( this.model.toJSON() ));
        return this;
    },

    close: function() {
        $(this.el).unbind();
        $(this.el).remove();
    },

    sendSelectedPhotoId: function() {
        console.log('clicked!');
        var self = this;
        console.log(self.model.get('photo_id'));
        self.model.fetch({
            data: { chosen_photo: self.model.get('photo_id')},
            processData: true,
            success: function() {
                $(this.el).html('');
        }});
    }


});

Problem: With this, I cant seem to fire the reset event of the model after doing the fetch() in function sendSelectedPhotoId , which means I cant get it to re-render using PhotoListView 's render() .

In the screenshot below from Chrome's javascript console, I printed out the collection after sendSelectedPhotoId did its fetch() , and it seems like the fetched added the new data to the existing model, instead of creating 2 new models and removing all existing model!

在此处输入图片说明

You already have child views for each model, so I would put the click event handler in the child view. In the handler in the child, trigger an event passing this.model, and listen for that event in your parent.

Update based on update:

Try changing

this.model.bind('reset', this.render, this); to 
this.model.bind('remove', this.render, this);  // model is a collection right?

and then remove the model from the collection after the view is clicked. Also, I don't think using Model.fetch is what you really want to do. Maybe a .save or a custom method on the model?

Update based on author's comment showing sample base from blog

I would not follow that blog's advice. If you are using backbone professionally I can't recommend the Thoughtbot ebook enough.

  • It's $50 for a work in progress, and it's worth every penny
  • It has a simple sample application that lays out how to organize a backbone app. This is why I bought the book.
  • It uses Rails in the examples for the backend, but I have used Rails, Node, and C# MVC and all work no problem.

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