Patrick Beeson
Patrick Beeson

Reputation: 1695

How to update Backbone JS model attribute?

UPDATE: I've updated my views to show how I resolved this question using information from the accepted answer.

I'd like to update/increment an attribute ('video_views') of my Backbone JS model via a click event from my view. But, as a Backbone rookie, I'm not sure how to accomplish this exactly.

I'd like the 'video_views' attribute to increment by one with the playVideo event (click).

Thanks for the help!

Here is the structure of my JSON from my API:

{
"id": 8,
"name": "Bike to work day",
"slug": "bike-work-day",
"tagline": "A brief tagline about the video.",
"description": "This is a test.",
"created": "2015-02-06T15:22:26.342658Z",
"website": "http://thevariable.com/",
"logo": "http://dev.thevariable.com/media/brands/logos/test_logo.jpeg",
"video": "http://dev.thevariable.com/media/brands/videos/3D463BC3-38B8-4A6F-BE93-3F53E918EC3B-3533-00000118880074BA_1.1.mp4",
"video_thumbnail": "http://dev.thevariable.com/media/brands/video_thumbnails/3D463BC3-38B8-4A6F-BE93-3F53E918EC3B-3533-00000118880074BA_1.1.mp4.jpg",
"links": {
"self": "http://dev.thevariable.com/api/brands/bike-work-day"
},
"status_display": "published",
"video_views": 0
}

Here are my Backbone views:

var TemplateView = Backbone.View.extend({
    templateName: '',
    initialize: function () {
        this.template = _.template($(this.templateName).html());
    },
    render: function () {
        var context = this.getContext(), html = this.template(context);
        this.$el.html(html);
    },
    getContext: function () {
        return {};
    }
});

var HomePageView = TemplateView.extend({
    templateName: '#home-template',
    events: {
        'click video': 'updateCounter',
        'click .video video': 'playVideo',
        'click .sound': 'muteVideo',
        'click .js-open-card': 'openCard'
    },
    initialize: function (options) {
        var self = this;
        TemplateView.prototype.initialize.apply(this, arguments);
        app.collections.ready.done(function () {
            app.brands.fetch({success: $.proxy(self.render, self)});
        });
    },
    getContext: function () {
        return {brands: app.brands || null};
    },
    updateCounter: function (e) {
        var id = $(e.currentTarget).data('id');
        var item = self.app.brands.get(id);
        var views = item.get('video_views');
        var video = this.$('.video video');
        // Only update the counter if the video is in play state
        if (video.prop('paused')) {
            item.save({video_views: views + 1}, {patch: true});
            this.render();
        }
    },
    playVideo: function () {
        var video = this.$('.video video');
        if (video.prop('paused')) {
          video[0].play();
        } else {
          video.get(0).pause();
        }
    },
    muteVideo: function (e) {
        e.preventDefault();
        var video = this.$el.parent().find('video');
        video.prop('muted', !video.prop('muted'));
        this.$('.sound').toggleClass('is-muted');
    },
    openCard: function (e) {
        e.preventDefault();
        this.$el.toggleClass('is-open');
        this.$el.closest('.card-container').toggleClass('is-open');
    }
});

And my Backbone models:

var BaseModel = Backbone.Model.extend({
    url: function () {
        var links = this.get('links'),
            url = links && links.self;
        if (!url) {
            url = Backbone.Model.prototype.url.call(this);
        }
        return url;
    }
});

app.models.Brand = BaseModel.extend({
    idAttributemodel: 'slug'
});

var BaseCollection = Backbone.Collection.extend({
    parse: function (response) {
        this._next = response.next;
        this._previous = response.previous;
        this._count = response.count;
        return response.results || [];
    },
    getOrFetch: function (id) {
        var result = new $.Deferred(),
            model = this.get(id);
        if (!model) {
            model = this.push({id: id});
            model.fetch({
                success: function (model, response, options) {
                    result.resolve(model);
                },
                error: function (model, response, options) {
                    result.reject(model, response);
                }
            });
        } else {
            result.resolve(model);
        }
        return result;
    }
});

app.collections.ready = $.getJSON(app.apiRoot);
app.collections.ready.done(function (data) {
    app.collections.Brands = BaseCollection.extend({
        model: app.models.Brand,
        url: data.brands
    });
    app.brands = new app.collections.Brands();
});

Upvotes: 1

Views: 3629

Answers (1)

Ryan Gill
Ryan Gill

Reputation: 1758

Just increment that attribute on the model and save it.

var views = model.get('video_views');

model.set({video_views: views + 1});

model.save();

Upvotes: 1

Related Questions