Backbone.js - Collection keeps getting reset after fetch.success gets called - backbone.js

I have existing items in a collection and I want to call fetch with a different url to bring in other items that will be merged in.
For some reason reset is being called even if I use the reset:false flag and I think it has something to do with my success callback.
Is there anyway to disable the reset event and still use the success callback?
My fetch looks like this:
self.collection.fetch({
url: url,
add: true,
reset: false,
success: function() {
self.render();
$('.loading').hide();
},
error: function() {
$('.loading').hide();
}
});

I have already faced this problem and solved like this. You can also try this
self.collection.fetch({
url: url,
add: true,
add: true,
remove: false,
update: true,
success: function() {
self.render();
$('.loading').hide();
},
error: function() {
$('.loading').hide();
}
});

Related

Why is not updated scope in Angular JS?

I have the following code Angular JS:
appService.get({id : id}).then(function (response) {
$scope.vm.events.push({title: 'New event', type: 'important', draggable: true, resizable: true});
})
This code returns response from AJAX service and puts object to array $scope.vm.events.
So, in template I dont see this added element as: {{vm.events}}
There is also one function in the same controller:
$scope.add = function (){
$scope.vm.events.push({title: 'New event', type: 'important', draggable: true, resizable: true});
}
When I call it I see new element in template: {{vm.events}}.
Why does not work code in the first case?
This is because the callback function in your service is outside the angularjs digest cycle.
For tackling this, there are two ways:
Method 1:
The first way would be to use $scope.$apply just after your callback in the service has finished as follows:
appService.get({id : id}).then(function (response) {
$scope.vm.events.push({title: 'New event', type: 'important', draggable: true, resizable: true});
$scope.$apply(); //this for updating your scope outside the digest cycle
})
Method 2:
Wrapping your service code inside a function inside the controller's scope as follows:
$scope.fn = function() {
appService.get({id : id}).then(function (response) {
$scope.vm.events.push({title: 'New event', type: 'important', draggable: true, resizable: true});
})
}
So, in this method, whenever you want to call the service just call this function. This is also the reason why your 'add' function updates the template because it is in the 'scope' of the controller and in the digest cycle.
If you are not seeing it, it is because the promise is not being resolved.
Do try putting something in the rejection handling part of the promise (on a second function within the 'then()' block):
appService.get({id : id}).then(function (response) {
$scope.vm.events.push({title: 'New event', type: 'important', draggable: true, resizable: true});
},
function(){
$scope.vm.events.push({title: 'ERROR_EVENT', type: 'ERROR_CALLBACK', draggable: true, resizable: true});
});
Like others suggested, if this is outside of angular, please call for $scope.$apply() or $scope.$digest() to trigger a digest cycle so that your data can be updated.
By adding this second function you should be able to see if the promise was being resolved or not, and if the problem lies elsewhere.

What would keep setter methods from being created in sencha touch

I have a simple controller that I'm starting to build in sencha touch 2:
Ext.define('ScoreKeeper.controller.GameScores', {
extend: 'Ext.app.Controller',
config: {
refs: {
requestButton: 'button[name=RequestButton]',
responseArea: '#scoreResponse'
},
control: {
requestButton: {
tap: 'sendRequest'
}
}
},
sendRequest: function (){
Ext.Ajax.request({
url: 'message',
method: 'GET',
disableCaching: false,
scope: this,
callback: function(options, success, response) {
this.setResponse(response.responseText);
}
});
},
setResponse: function (responseText){
this.setResponseArea(responseText);
}
});
When I tap my requestButton the sendRequest method fires correctly but when it gets to the setResponse method, it fails on the this.setResponseArea step.
When I checked my browser dev tools, it looks like the getter methods for both of my refs get created, but neither of the setter methods do.
What would keep these methods from being created?
Assuming #responseArea refers to an HTML element like a <div>. To attribute the response from your server to the HTML element, do this:
this.getResponseArea.setHtml(responseText);
instead of
this.setResponseArea(responseText);.
Don't forget getResponseArea gets you the HTML element with #responseArea as id. When you got it, you can do whatever you want with it; for example:
this.getResponseArea.setValue(responseText);
or
this.getResponseArea.getValue();.
That's why there is a get but no set.

Sencha Touch Load Mask

I have list and pull down to refresh plugin in it. When the refresh function fires i would like to show the load mask. But its not showing there. when i commented store.removeAll(); line i can see the loadmask working. I dont konw whats the problem with store.removeAll(). Please help me to solve this issue. Thanks in advance
{
xclass: 'Ext.ux.PullRefreshFn',
pullRefreshText: 'Pull down for refresh Contacts!',
refreshFn: function() {
console.log('pull refresh working');
Ext.Viewport.setMasked({
xtype: 'loadmask',
message: 'Please Wait...'
});
var store = Ext.getStore('Contactsstore');
store.removeAll();
var url = apiurl+'Contact.ashx?switch=GetContactList&api_id=4&getDataAgain=true';
store.getProxy().setUrl(url);
store.loadPage(1,{
callback: function (records, operation, success, response) {
if (success==1) {
Ext.Viewport.setMasked(false);
} else {
Ext.Viewport.setMasked(false);
}
}
});
Ext.getCmp('searchcontact').reset();
}
}
Here is my Store configuration
Ext.define('WinReo.store.Contactsstore', {
extend: 'Ext.data.TreeStore',
requires: [
'WinReo.model.Contactsmodel'
],
config: {
storeId: 'Contactsstore',
defaultRootProperty: 'items',
model: 'WinReo.model.Contactsmodel',
autoLoad: false,
pageSize: 20,
proxy: {
type: 'ajax',
method:'post',
id: 'Contactsstoreproxy',
url:apiurl+'Contact.ashx?switch=GetContactList&api_id=4&getDataAgain=false',
reader: {
type: 'json',
rootProperty: 'items'
}
},
listeners: {
load: function(store, records, successful, operation, eOpts) {
callback:{
succes:
if(store.getCount()!=0){
var RecordCount=store.getAt(0).get('RecordCount');
//console.log('RecordCount',RecordCount);
store.setTotalCount(RecordCount);
var storectscount = store.getTotalCount();
//Ext.Msg.alert('Store Total count',storectscount, Ext.emptyFn);
}
}
}
}
}
}
});
Loading masks won't get rendered until the browser has a chance to render them, and that won't happen until your Javascript code completes. I suspect that for some reason, the removeAll call isn't completing quickly (or at all), or an event listener on clear isn't completing like it needs to. Check your store's configuration for syncRemovedRecords: true and autoSync: true. You can also try removeAll(true) to keep the clear event from firing.
Update
Looking at your store definition, I can see at least one problem: Your load listener doesn't look like it's defined properly. You're defining a callback field inside of a function (which isn't going to compile), and 'succes' is misspelled. Is this what you had in mind?
load: function(store, records, successful, operation, eOpts) {
if(successful === true && store.getCount()!=0){
var RecordCount=store.getAt(0).get('RecordCount');
store.setTotalCount(RecordCount);
}
}
}

Backbone on('add') not being called

I defined the add handler on my collection:
var BookmarksCollection = Backbone.Collection.extend({
initialize: function() {
this.on('add', function(obj) {
console.log(obj.get('title') + ' added');
});
},
url: '/bookmarks',
model: Bookmark
});
And it's being called from one of my views:
var AddView = Backbone.View.extend({
el: $('#entry'),
events: {
'click #submit': 'submitHandler'
},
submitHandler: function(event) {
if($('input').val()) {
var newBookmark = new Bookmark;
newBookmark.set({url: $('input').val()});
console.log('Save!');
newBookmark.save({
success: function(newBookmark) {
console.log('Success!');
myBookmarks.add(newBookmark);
myBookmarks.trigger('add', newBookmark);
}
});
}
}
});
However the add handler on my collection is never triggered. In fact, not even the success function in the view seems to be called.
But the newBookmark gets saved anyway, so no errors happening.
What am I missing?
NodeJS respond with 201 (Created) when a new bookmark is posted.
Maybe backbone expects a 200 (OK) to trigger success?
EDIT: I tried triggering the event from outside the success function and it works.
How can I tweak backbone to react to a 201 (Created)?
I think the issue is that he first argument of save should be the data you are trying to save. The second is the options which can include the success and error callbacks.
newBookmark.save({dataiwanttosave: "hi"}, {
success: function(newBookmark) {
console.log('Success!');
myBookmarks.add(newBookmark);
myBookmarks.trigger('add', newBookmark);
}
});

Backbone collection 0.9.9 - add event not work

Backbone collection 0.9.9 - add event not work
After update backbone to 0.9.9, i have a problem with (add).
(function () {
var Model = Backbone.Model.extend({
initialize: function () {
console.log('initialize Model');
}
});
var Collection = Backbone.Collection.extend({
model: Model,
url: "/json.json",
initialize: function () {
console.log('initialize Collection');
}
});
var View = Backbone.View.extend({
initialize: function () {
console.log('initialize View');
}
});
var collection = new Collection([
{
"id" : "001",
"name" : "Дарья",
"text" : "1 Вопрос - Ответ 1"
}
]);
collection.on('add', function () {
console.log('edd event', this)
});
collection.fetch({
add: true,
//silent: false,
success: function (model) {
console.log('fetch')
}
});
}());
console.log('edd event', this) - not work (
in old versions it works
It would appear that the add option to collection.fetch is no longer supported.
From 0.9.2 source (collection.fetch):
collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options);
From 0.9.9 source (collection.fetch):
var method = options.update ? 'update' : 'reset';
collection[method](resp, options);
if (success) success(collection, resp, options);
So by default collection.fetch will cause a reset on the collection, and the resetevent will be fired. If you pass option update:true, and update will be performed.
According to documentation for the new collection.update method, update will trigger the add events for added models, so the following should work:
collection.fetch({
update: true,
success: function (model) {
console.log('fetch')
}
});
Just test and be aware, that the new update method will also trigger remove and changeevents, if models are removed or changed.
You need to remove the commented out line because it won't propagate the add events otherwise (see line 827 of the backbone.js source). So the following should work
collection.fetch({
add: true,
silent: false,
success: function (model) {
console.log('fetch')
}
});
I'm not sure if that's a change from previous versions :)
From what I gather from checking out the Backbone 0.9.9 source, the add -option does nothing with fetch unless you add in the update - option as well. source
So to do something useful with it do the following:
collection.fetch({
add: true,
update: true, // this is necessary as well
//silent: false,
success: function (model) {
console.log('fetch')
}
});
This is also the cause for your problem. When you fetch, the Collection automatically defaults to the reset -function after fetching. reset silences the add -events and opts to just trigger a reset event as is evident from the Backbone.js source
if (models) this.add(models, _.extend({silent: true}, options));
So use the update option if you want the add -events and do not want to empty the collection before adding the new models. If you must have the reset functionality AND the add event, then you might have to write some custom implementation of reset.

Resources