How to update Backbone JS model attribute? - javascript

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();
});

Just increment that attribute on the model and save it.
var views = model.get('video_views');
model.set({video_views: views + 1});
model.save();

Related

Issues searching backbone collection

I have this bb app that I'm trying to search and return the results of the search, then when cleared, so all results again. I was able to get everything to show before adding the search feature, but now nothing showing up. I think the collection isn't available at the time it's trying to populate, but can't seem to get it to wait. I've tried moving the fetch around to no avail. Any help would be greatly appreciate. For the sake of ease, I've put everything in a fiddle that can be found here...
//Campaign Model w defaults
app.model.Campaign = Backbone.Model.extend({
default: {
title: '',
img: '',
id: '',
slug: '',
image_types: 'small',
tagline: ''
}
});
//Campaign Collection from model
app.collection.Campaign = Backbone.Collection.extend({
//our URL we're fetching from
url: 'https://api.indiegogo.com/1/campaigns.json?api_token=e377270bf1e9121da34cb6dff0e8af52a03296766a8e955c19f62f593651b346',
parse: function(response) {
console.log('parsing...');
return response.response; //get array from obj to add to collection based on model
},
currentStatus: function(status){
return _(this.filter(function(data){
console.log('currentStats', status);
return data.get('_pending') == status;
}));
},
search: function(searchVal) {
console.log('search...');
if (searchVal == '') {
return this;
}
var pattern = new RegExp(searchVal, 'gi');
return _(this.filter(function(data) {
return pattern.test(data.get('title'));
}));
}
});
app.collection.campaigns = new app.collection.Campaign();
app.collection.campaigns.fetch({
success: function(){
console.log('Success...');
var sHeight = window.screen.availHeight - 200 + 'px';
$('#container ul').css('height', sHeight);
},
error: function() {
console.log('error ',arguments);
}
});
//List view for all the campaigns
app.view.CampaignList = Backbone.View.extend({
events: {
'keyup #searchBox': 'search'
},
render: function(data) {
console.log('campaignList',$(this.el).html(this.template));
$(this.el).html(this.template);
return this;
},
renderAll: function(campaigns) {
console.log('campList renderAll', campaigns, $('#campaignList'));
$('#campaignList').html('');
campaigns.each(function(campaign){
var view = new app.view.CampaignItem({
model: campaign,
collection: this.collection
});
console.log(view);
$('#campaignList').append(view.render().el);
});
return this;
},
initialize: function() {
console.log('init campList',app);
this.template = _.template($('#campaignList-tmp').html());
this.collection.bind('reset', this.render, this);
},
search: function(e) {
console.log('listView search');
var searchVal = $('#searchBox').val();
this.renderAll(this.collection.search(searchVal));
},
sorts: function() {
var status = $('#campSorting').find('option:selected').val();
if(status == '') {
status = false;
};
this.renderAll(this.collection.currentStatus(status));
}
});
//Item view for single campaign
app.view.CampaignItem = Backbone.View.extend({
events: {},
render: function(data){
console.log('campItem render...', data);
this.$el.html(this.template(this.model.toJSON()));
return this;
},
initialize: function(){
console.log('campItem init');
this.template = _.template( $('#campaignItem-tmp').html());
}
});
//Router
app.router.Campaign = Backbone.Router.extend({
routes: {
'': 'campaigns'
},
campaigns: function(){
this.campListView = new app.view.CampaignList({
collection: app.collection.campaigns
});
$('#container').append(this.campListView.render().el);
this.campListView.sorts();
}
});
app.router.campaigns = new app.router.Campaign();
Backbone.history.start();
http://jsfiddle.net/skipzero/xqvrpyx8/

How can i call function on view on the click event of Id, function is written on controller in backbone.js

My controller code is here.
spine.module("communityApp", function (communityApp, App, Backbone, Marionette, $, _) {
"use strict";
communityApp.Controllers.pforumController = Marionette.Controller.extend(
{
init: function(){
var func = _.bind(this._getpforum, this);
var request = App.request('alerts1:entities' , {origin:'pforum'});
$.when(request).then(func)
},
_getpforum:function(data){
var pforumCollectionView = new communityApp.CollectionViews.pforumCollectionViews({
collection: data
});
communityApp.activeTabView = pforumCollectionView;
// Populating the data
communityApp.activeTabLayout.pforum.show(pforumCollectionView);
},
});
});
view code is here
spine.module("communityApp", function (communityApp, App, Backbone, Marionette, $, _) {
// Load template
var a;
var pforumTemplateHtml = App.renderTemplate("pforumTemplate", {}, "communityModule/tabContainer/pforum");
// Define view(s)
communityApp.Views.pforumView = Marionette.ItemView.extend({
template: Handlebars.compile($(pforumTemplateHtml).html()),
tagName: "li",
onRender: function () {
this.object = this.model.toJSON();
},
events: {
"click #postcomment" : "alrt",
"click #recent-btn": "recent",
"click #my-posts": "myposts",
"click #popular-btn": "popular",
"click #follow-btn": "follow",
"click #my-posts": "LeftLinks",
"click #popular-btn": "LeftLinks",
"click #follow-btn": "LeftLinks"
},
postcomments : function ()
{
$("#recent-post-main-container").hide();
$("#recent-post-main-container2").show();
},
alrt : function ()
{
alert ("In Progress ......");
},
showCommentEiditor : function (){
$(".comment-popup-container").show();
$(".comment-txt-area").val('');
},
showPforumTab : function ()
{
$("#recent-post-main-container2").show();
$("#recent-post-main-container").hide();
},
showComments : function(){
$("#loading").show();
$(".tab-pane").hide();
$(".left-content").hide();
$("#recent-post-main-container2").show();
//$(".left-content-commentEditor").show();
$(".comm-tab-content-container").css('height','200px');
$(".comment-txt-area").val('');
$(".left-content-comment").show();
},
hideCommentPopup : function ()
{
$("#public-question-comment").hide();
},
// Show Loading sign
showLoading : function () {
$('#loading').show();
},
// UnLoading Function
hideLoading : function (){
$('#loading').hide();
},
// Add New Event Function
addEvent : function()
{
//$("#name").val(getBackResponse.user.FullName);
//$("#phone").val(getBackResponse.user.CellPhone);
//$("#email").val(getBackResponse.user.UserName);
$(".overly.addevent").show();
$('#lang').val(lat);
$('#long').val(long);
document.getElementById("my-gllpMap").style.width = "100%";
var my_gllpMap = document.getElementById("my-gllpMap");
google.maps.event.trigger( my_gllpMap, "resize" );
},
setValues : function(key,value)
{
window.localStorage.setItem(key,value);
},
getValues : function (key)
{
return window.localStorage.getItem(key);
},
closeAddEvent:function ()
{
$(".overly.addevent").hide();
},
// Show Over lay
showOverly:function ()
{
$('.overly-right-tab').show();
},
// Hide Loading sign
hideOverly : function()
{
$('.overly-right-tab').hide();
},
LeftLinks: function (e) {
var elem = $(e.target).closest('a');
var elem = $(e.target).closest('a');
var event = elem.attr('name');
switch (event) {
case "myposts":
var _this = $.extend({}, this, true);
_this.event = 'myposts';
this.LinkUrl.call(_this);
//$("#my-posts").addClass('active');
//$("#public-fourm-top-tab").addClass('TabbedPanelsTabSelected');
//$(".types").removeClass('active');
break;
case "recents":
var _this = $.extend({}, this, true);
_this.event = 'recents';
this.LinkUrl.call(_this);
$(".types").removeClass('active');
$("#recent-btn").addClass('active')
//$("#pforum").removeClass('active');
// $("#recent").addClass('active');
break;
case "populars":
var _this = $.extend({}, this, true);
_this.event = 'populars';
this.LinkUrl.call(_this);
$(".types").removeClass('active');
$("#popular-btn").addClass('active')
// $("#pforum").removeClass('active');
//$("#popular").addClass('active');
break;
case "follows":
var _this = $.extend({}, this, true);
_this.event = 'follows';
this.LinkUrl.call(_this);
$(".types").removeClass('active');
$("#follow-btn").addClass('active')
break;
}
},
LinkUrl: function (modalThis) {
communityApp.activeTabView.collection = []; // currently empty data
communityApp.activeTabView.render();
className: 'comm-main-container'
// uncomment these lines when getting data fro web service route, it will repopulate the data
var func = _.bind(function (data) {
communityApp.activeTabView.collection = data;
communityApp.activeTabView.render();
}, this);
switch (this.event) {
case "myposts":
$.when(App.request('alertLinks:entities', {
origin: 'pforum',
event: this.event
})).then(func);
break;
case "recents":
$.when(App.request('alertLinks:entities', {
origin: 'pforum',
event: this.event
})).then(func);
break;
case "populars":
$.when(App.request('alertLinks:entities', {
origin: 'pforum',
origin1:'popular',
event: this.event
})).then(func);
break;
case "follows":
$.when(App.request('alertLinks:entities', {
origin: 'pforum',
event: this.event
})).then(func);
break;
}
return true;
}
});
// define collection views to hold many communityAppView:
communityApp.CollectionViews.pforumCollectionViews = Marionette.CollectionView.extend({
tagName: "ul",
itemView: communityApp.Views.pforumView
});
});
Whenever I need to share an event between a view and controller I usually wire up the listeners within the module that instantiates the controller. This example is a bit contrived, but it gets the point across. The full working code is in this codepen. The relevant bit is copied here. Notice the line this.listenTo(view, 'itemview:selected', this.itemSelected); where the view's event triggers a method on the controller.
App.module("SampleModule", function(Mod, App, Backbone, Marionette, $, _) {
// Define a controller to run this module
// --------------------------------------
var Controller = Marionette.Controller.extend({
initialize: function(options){
this.region = options.region
},
itemSelected: function (view) {
var logView = new LogView();
$('#log').append(logView.render('selected:' + view.cid).el);
},
show: function(){
var collection = new Backbone.Collection(window.testData);
var view = new CollectionView({
collection: collection
});
this.listenTo(view, 'itemview:selected', this.itemSelected);
this.region.show(view);
}
});
// Initialize this module when the app starts
// ------------------------------------------
Mod.addInitializer(function(){
Mod.controller = new Controller({
region: App.mainRegion
});
Mod.controller.show();
});
});
The other way to accomplish this, if you cannot wire it all up within the same module, is to use Marionette's messaging infrastructure. For example, you can use the application's event aggregator to pass events around.

Trouble using two models in one view for backbone

I'm having trouble in attempting to use two models with the same view in backbone.js. Somehow the view is being rendered before the triggers are getting triggered to begin the render function.
Here are the models:
APP.Models.FamilyPreferences = Backbone.Model.extend({
initialize: function( attributes, options ) {
_.bindAll(this, 'success_handler', 'populate');
this.url = options.url;
},
populate: function(){
this.fetch({success: this.success_handler});
},
success_handler: function(){
this.trigger("change");
}
});
APP.Models.Preferences = Backbone.Model.extend({
initialize: function( attributes, options ) {
_.bindAll(this, 'success_handler', 'error_handler', 'populate');
this.url = options.url;
},
populate: function(){
this.fetch({success: this.success_handler, error:this.error_handler});
},
success_handler: function(){
this.exists = true;
this.trigger("change");
},
error_handler: function(){
this.exists = false;
this.trigger("change");
}
});
Here is the relevant code from the view:
APP.Views.PreferencesFormView = Backbone.View.extend({
templates: [{name:"preferences_template", file_path:"preferences_form.html"}],
initialize: function(options){
_.bindAll(this, 'render', 'renderPrereq');
var family_url = "services/family/" + options.family_id;
var preferences_url = "services/preferences/familyID/" + options.family_id;
var ctx = this;
this.alreadyRendered = false;
this.modelsCurrentlyLoaded = [];
this.models = {};
this.models.family = new APP.Models.FamilyPreferences({}, {url: family_url});
this.models.family.on('change', function(){ctx.renderPrereq("family");});
this.models.family.populate();
this.models.preferences = new APP.Models.Preferences({}, {url:preferences_url});
this.models.preferences.on('change', function() {ctx.renderPrereq("preferences");});
this.models.preferences.populate();
},
renderPrereq: function(newmodel){
var inside = ($.inArray(newmodel, this.modelsCurrentlyLoaded)>-1) ? true : false;
if (!(inside)){this.modelsCurrentlyLoaded.push(newmodel);}
var total = Object.keys(this.models).length;
if(this.modelsCurrentlyLoaded.length == total && !this.alreadyRendered){
this.alreadyRendered = true;
this.render();
}
},
render: function(){
var family_data = {
id: this.models.family.attributes.id,
familyGroup: this.models.family.attributes.groupNum,
familyId: this.models.family.attributes.familyId,
probandDob: this.models.family.attributes.childDob,
}
var preferences_data = {
mother: this.models.preferences.attributes[0],
father: this.models.preferences.attributes[1],
exists: this.models.preferences.exists
}
this.$el.html(this.compiledTemplates.preferences_template(family_data));
//bunch of javascript making the page work
}
});
The template are getting loaded through another js function elsewhere that to the best of my knowledge is working correctly. Somehow the render function is getting called before the success handlers. I can't figure out how. The only side effect it has is that the Preferences model doesn't get the exists property and is hence undefined which cause all sorts of problems. Also, options.family_id is set correctly. Any help would be appreciated. Thank you in advance.
EDIT: It also seems to be going to renderPrereq up to six times which I also can't figure out.
JSON - Family model
{
"id": 1,
"familyId": "family01",
"collectionDate": "2013-01-01",
"childDob": "2001-05-‌​06",
"groupNum": "Two",
"probands": [],
"mother": null,
"father": null,
"siblings": []
}
JSON - First part of Preferences Model
[{
"main": "illness-only",
"obesity": "No",
"bloodPressure": "No",
"diabetes": "No",
"hea‌​rt": "No",
"alzheimers": "No",
"parkinsons": "No",
"mentalHealth": "No",
"breastOvarianCa‌​ncer": "No",
"prostateTesticularCancer": "No",
"otherCancer": "No",
"childSickleCell": "‌​No",
"childCysticFibrosis": "No",
"childMuscularDystrophy": "No",
"childAutism": "No"
},
{
"main":"more-questions",
"obesity":"No",
"bloodPressure":"Yes",
"diabetes":"No",
"heart":"Unsure",
"alzheimers":"No",
"parkinsons":"Yes",
"mentalHealth":"No",
"breastOvarianCancer":"No",
"prostateTesticularCancer":"No",
"otherCancer":"No",
"childSickleCell":"No",
"childCysticFibrosis":"No",
"childMuscularDystrophy":"No",
"childAutism":"No"}]
Headers
Accept: application / json, text / javascript, /; q=0.01
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache Connection:keep-alive
Cookie:csrftoken=bDIpdvAPBdWF6dZe9BkpsFSF4wiGl2qX
Host:localhost:8080 Pragma:no-cache Referer:localhost:8080/CSER / index.html
User - Agent: Mozilla / 5.0(Macintosh; Intel Mac OS X 10_8_3) AppleWebKit /
537.36(KHTML, like Gecko) Chrome / 27.0.1453.110 Safari / 537.36 X - Requested - With: XMLHttpRequest
Try this code ..
APP.Models.FamilyPreferences = Backbone.Model.extend({
initialize: function (attributes, options) {
_.bindAll(this, 'success_handler', 'populate');
this.url = options.url;
},
populate: function () {
this.fetch();
},
// This is not required
// It will automatically render it as we are listening to the sync event
success_handler: function () {
// Not required
// sync event will take care of it
}
});
APP.Models.Preferences = Backbone.Model.extend({
initialize: function (attributes, options) {
_.bindAll(this, 'success_handler', 'error_handler', 'populate');
this.url = options.url;
},
populate: function () {
this.fetch({
success: this.success_handler,
error: this.error_handler
});
},
success_handler: function () {
this.exists = true;
// Not required
// sync event will take care of it
},
error_handler: function () {
// Do something else
}
});
APP.Views.PreferencesFormView = Backbone.View.extend({
templates: [{
name: "preferences_template",
file_path: "preferences_form.html"
}],
initialize: function (options) {
_.bindAll(this, 'render', 'renderPrereq');
var family_url = "services/family/" + options.family_id;
var preferences_url = "services/preferences/familyID/" + options.family_id;
var ctx = this;
this.alreadyRendered = false;
this.modelsCurrentlyLoaded = [];
this.models = {};
// Family Model
this.models.family = new APP.Models.FamilyPreferences({}, {
url: family_url
});
this.listenTo( this.models.family, 'change', function () {
ctx.renderPrereq("family");
});
// This will take care of rendering it on Sync with server
// No need to triggereing the event explicitly..
this.listenTo( this.models.family, 'sync', function () {
ctx.renderPrereq("family");
});
this.models.family.populate();
// Family Preference Model
this.models.preferences = new APP.Models.Preferences({}, {
url: preferences_url
});
this.listenTo( this.models.preferences, 'change', function () {
ctx.renderPrereq("family");
});
// This will take care of rendering it on Sync with server
// No need to triggereing the event explicitly..
this.listenTo( this.models.preferences, 'sync', function () {
ctx.renderPrereq("preferences");
});
this.models.preferences.populate();
},
renderPrereq: function (newmodel) {
var inside = ($.inArray(newmodel, this.modelsCurrentlyLoaded) > -1) ? true : false;
if (!(inside)) {
this.modelsCurrentlyLoaded.push(newmodel);
}
var total = Object.keys(this.models).length;
if (this.modelsCurrentlyLoaded.length == total && !this.alreadyRendered) {
this.alreadyRendered = true;
this.render();
}
},
render: function () {
var family_data = this.models.family.toJSON());
var preferences_data = {
mother: this.models.preferences.attributes[0],
father: this.models.preferences.attributes[1],
exists: this.models.preferences.get('exists') ? this.models.preferences.get('exists') : false
}
this.$el.html(this.compiledTemplates.preferences_template(family_data);
//bunch of javascript making the page work
}
});
Looks like the problem is the way it is constructed... I don't think the render is called before success_handler .
If you look at the renderPrereq method , 2 models on change will call this method on success.
But the fetch methods are async. So you never know which handler will be called first.
And when the change on the model is triggered. This calls the render method which is inside the renderPrereq method.

GUI component for display async request states

Which interface or component do you suggest to display the state of parallel async calls? (The language is not so important for me, just the pattern, I can rewrite the same class / interface in javascript...)
I load model data from REST service, and I want to display pending label before the real content, and error messages if something went wrong... I think this is a common problem, and there must be an already written component, or best practices, or a pattern for this. Do you know something like that?
Here is a spaghetti code - Backbone.syncParallel is not an existing function yet - which has 2 main states: updateForm, updated. Before every main state the page displays the "Please wait!" label, and by error the page displays an error message. I think this kind of code is highly reusable, so I think I can create a container which automatically displays the current state, but I cannot decide what kind of interface this component should have...
var content = new Backbone.View({
appendTo: "body"
});
content.render();
var role = new Role({id: id});
var userSet = new UserSet();
Backbone.syncParallel({
models: [role, userSet],
run: function (){
role.fetch();
userSet.fetch();
},
listeners: {
request: function (){
content.$el.html("Please wait!");
},
error: function (){
content.$el.html("Sorry, we could not reach the data on the server!");
},
sync: function (){
var form = new RoleUpdateForm({
model: role,
userSet: userSet
});
form.on("submit", function (){
content.$el.html("Please wait!");
role.save({
error: function (){
content.$el.html("Sorry, we could not save your modifications, please try again!");
content.$el.append(new Backbone.UI.Button({
content: "Back to the form.",
onClick: function (){
content.$el.html(form.$el);
}
}));
},
success: function (){
content.$el.html("You data is saved successfully! Please wait until we redirect you to the page of the saved role!");
setTimeout(function (){
controller.read(role.id);
}, 2000);
}
});
}, this);
form.render();
content.$el.html(form.$el);
}
}
});
I created a custom View to solve this problem. (It is in beta version now.)
Usage: (Form is a theoretical form generator)
var content = new SyncLabelDecorator({
appendTo: "body",
});
content.load(function (){
this.$el.append("normal html without asnyc calls");
});
var User = Backbone.Model.extend({
urlRoot: "/users"
});
var UserSet = Backbone.Collection.extend({
url: "/users",
model: User
});
var Role = Backbone.RelationalModel.extend({
relations: [{
type: Backbone.HasMany,
key: 'members',
relatedModel: User
}]
});
var administrator = new Role({id :1});
var users = new UserSet();
content.load({
fetch: [role, users],
sync: function (){
var form = new Form({
title: "Update role",
model: role,
fields: {
id: {
type: "HiddenInput"
},
name: {
type: "TextInput"
},
members: {
type: "TwoListSelection",
alternatives: users
}
},
submit: function (){
content.load({
tasks: {
save: role
},
sync: function (){
this.$el.html("Role is successfully saved.");
}
});
}
});
this.$el.append(form.render().$el);
}
});
Code:
var SyncLabelDecorator = Backbone.View.extend({
options: {
pendingMessage: "Sending request. Please wait ...",
errorMessage: "An unexpected error occured, we could not process your request!",
load: null
},
supported: ["fetch", "save", "destroy"],
render: function () {
if (this.options.load)
this.load();
},
load: function (load) {
if (load)
this.options.load = load;
this._reset();
if (_.isFunction(this.options.load)) {
this.$el.html("");
this.options.load.call(this);
return;
}
_(this.options.load.tasks).each(function (models, method) {
if (_.isArray(models))
_(models).each(function (model) {
this._addTask(model, method);
}, this);
else
this._addTask(models, method);
}, this);
this._onRun();
_(this.tasks).each(function (task) {
var model = task.model;
var method = task.method;
var options = {
beforeSend: function (xhr, options) {
this._onRequest(task, xhr);
}.bind(this),
error: function (xhr, statusText, error) {
this._onError(task, xhr);
}.bind(this),
success: function (data, statusText, xhr) {
this._onSync(task, xhr);
}.bind(this)
};
if (model instanceof Backbone.Model) {
if (method == "save")
model[method](null, options);
else
model[method](options);
}
else {
if (method in model)
model[method](options);
else
model.sync(method == "fetch" ? "read" : (method == "save" ? "update" : "delete"), model, options);
}
}, this);
},
_addTask: function (model, method) {
if (!_(this.supported).contains(method))
throw new Error("Method " + method + " is not supported!");
this.tasks.push({
method: method,
model: model
});
},
_onRun: function () {
this.$el.html(this.options.pendingMessage);
if (this.options.load.request)
this.options.load.request.call(this);
},
_onRequest: function (task, xhr) {
task.abort = function () {
xhr.abort();
};
},
_onError: function (task, xhr) {
this._abort();
this.$el.html(this.options.errorMessage);
if (this.options.load.error)
this.options.load.error.call(this);
},
_onSync: function (task, xhr) {
++this.complete;
if (this.complete == this.tasks.length)
this._onEnd();
},
_onEnd: function () {
this.$el.html("");
if (this.options.load.sync)
this.options.load.sync.call(this);
},
_reset: function () {
this._abort();
this.tasks = [];
this.complete = 0;
},
_abort: function () {
_(this.tasks).each(function (task) {
if (task.abort)
task.abort();
});
}
});

Backbone Fetching Process

I have Backbone Model that collect data from server:
Job.Models.Response = Backbone.Model.extend({
defaults: {
'authStatus': false,
'id': '1',
'name': 'name',
},
urlRoot: '/static/js/public/json/'
});
I have button with data-id = "id from /static/js/public/json/".
Job.Views.Response = Backbone.View.extend({
el: '.ra-response-button',
events: {
"click": "load"
},
load: function () {
var info = this.$el.data();
this.model.set({ id: info.id});
this.model.fetch();
if (this.model.attributes.authStatus === false) {
console.log('Register')
}
else {
console.log('Unregister')
}
}
});
If i console.log my model after fetch, its dont update, but data fetch success.
What kind of problem can be here?
Here i init our plugin:
var responseModel = new Job.Models.Response;
var response = new Job.Views.Response({ model: responseModel });
I resolve my problem. Finally View.
Job.Views.Response = Backbone.View.extend({
el: '.ra-response-button',
events: {
"click": "load"
},
load: function () {
var that = this;
var info = that.$el.data();
that.model.set({ id: info.id});
that.model.fetch({
success: function() {
if (that.model.attributes.authStatus === true) {
new Job.Views.ResponseForm({ model: that.model })
}
else {
new Job.Views.ResponseAuth({ model : that.model })
}
},
error: function() {
alert('Error, repeat please.')
}
});
}
});

Categories

Resources