So basically, I created a Backfire app. As soon as the page is loaded, I am iterating over my Backbone.Firebase.Collection instance.
And then rendering the results onto the page... the problem is that obviously the collection instance does not contain all the data that is on firebase.
So, I put a set-timeout of 1000ms to make it so that the collection has time get its data from Firebase. This way of doing it is terrible... sometimes the data is synced up other times it is not.
How can I have an event be triggered as soon as the "BackFire Collection Model" has its data from firebase?
$(document).ready(function() {
var myCatalogApp = new CatalogApp()
var catalog = new Catalog()
setTimeout(function(){myCatalogApp.displayCollection(catalog)},1000);
//To give catalog time to asynchronously retrieve database entries
myCatalogApp.initialize()
})
var Catalog = Backbone.Firebase.Collection.extend({
model: Item,
firebase: "https://mycatalogmaker.firebaseIO.com/items"
});
All of my problems would be solved if Backfire would let me do a fetch method... but they have it disabled for Backfire objects
Try this :
$(document).ready(function() {
var myCatalogApp = new CatalogApp()
var catalog = new Catalog();
catalog.bind('sync', function(){myCatalogApp.displayCollection(catalog);});
myCatalogApp.initialize();
})
Related
I got the following AngularJS sample code from the document regarding how to add a new record to Firebase. It works fine and the new record can be created successfully.
While I also noticed that from the callback we can get all the siblings with the list variable, which is interesting.
My question is that would there be any performance latency when the list is large, say 100,000 records. Can anyone shed light on this?
var list = $firebaseArray(ref);
list.$add({ foo: "bar" }).then(function(ref) {
var id = ref.key();
console.log("added record with id " + id);
list.$indexFor(id); // returns location in the array
});
$firebaseArray synchronizes a collection from the Firebase Database to your client, for easy display in your Angular views. You should never synchronize more data than the user needs to see, and 100,000 records seems very much beyond what a user should ever see.
If you just want to add a new item, you're better off using the Firebase JavaScript SDK directly:
ref.push({ foo: "bar" }).then(function(ref) {
var id = ref.key();
console.log("added record with id " + id);
});
Since AngularFire is built on top of the Firebase JavaScript SDK, it will pick up this change automatically.
I want to retrieve data from firbase with a condition like this
ref.orderByChild('users').equalTo(userid).on('value', function(snapshot) {
// Need to return data as firebaseArray here
});
$firebaseArray is very useful when we want to show data on view. But I don't know how to return the snapshot there.
Please help me ! (bow)
A $firebaseArray can take in a ref or a query.
var query = ref.orderByChild('users').equalTo(userid);
var syncArray = $firebaseArray(query);
The array function handles all the child events and keeps the array in sync with the remote server changes.
I would like to update the view even if the change happened from a different computer without refreshing the page.I tried to set interval and call my api every ten seconds,clear my cache.The problem here is that every ten seconds i would have to reload all my data and for the view to be update i should switch states.Is there a better way to handle this?
im managed to resolve the issue.I created a function that check if the data from server is equal with the data from the model and if not i update the cache without deleting it and the model.
this.refresh = function(){
apiService.someFunction(false) //the false is parametr for cache
.then(function(someValue) {
if(someValue.length !== vm.model.length){ //check if the model is equal with the data from database
var cache = $cacheFactory.get('$http')
var get = cache.get('URL'); //getting the cache
var data = angular.toJson(someValue); //turn response from then to Json
get[1] = data; //changing the cache data
vm.model= someValue; //changing the model data
}
})
}
i am very confuse about using backbone.js model fetch method. See the following example
backbone router:
profile: function(id) {
var model = new Account({id:id});
console.log("<---------profile router-------->");
this.changeView(new ProfileView({model:model}));
model.fetch();
}
the first step, the model account will be instantiated, the account model looks like this.
define(['models/StatusCollection'], function(StatusCollection) {
var Account = Backbone.Model.extend({
urlRoot: '/accounts',
initialize: function() {
this.status = new StatusCollection();
this.status.url = '/accounts/' + this.id + '/status';
this.activity = new StatusCollection();
this.activity.url = '/accounts/' + this.id + '/activity';
}
});
return Account;
});
urlRoot property for what is it? After model object created, the profileview will be rendered with this this.changeView(new ProfileView({model:model}));, the changeview function looks like this.
changeView: function(view) {
if ( null != this.currentView ) {
this.currentView.undelegateEvents();
}
this.currentView = view;
this.currentView.render();
},
after render view, profile information will not display yet, but after model.fetch(); statement execute, data from model will be displayed, why? I really don't know how fetch works, i try to find out, but no chance.
I'm not entirely sure what your question is here, but I will do my best to explain what I can.
The concept behind the urlRoot is that would be the base URL and child elements would be fetched below it with the id added to that urlRoot.
For example, the following code:
var Account = Backbone.Model.extend({
urlRoot: '/accounts'
});
will set the base url. Then if you were to instantiate this and call fetch():
var anAccount = new Account({id: 'abcd1234'});
anAccount.fetch();
it would make the following request:
GET /accounts/abcd1234
In your case there, you are setting the urlRoot and then explicitly setting a url so the urlRoot you provided would be ignored.
I encourage you to look into the Backbone source (it's surprisingly succinct) to see how the url is derived: http://backbonejs.org/docs/backbone.html#section-65
To answer your other question, the reason your profile information will not display immediately is that fetch() goes out to the network, goes to your server, and has to wait for a reply before it can be displayed.
This is not instant.
It is done in a non-blocking fashion, meaning it will make the request, continue on doing what it's doing, and when the request comes back from the server, it fires an event which Backbone uses to make sure anything else that had to be done, now that you have the model's data, is done.
I've put some comments in your snippet to explain what's going on here:
profile: function(id) {
// You are instantiating a model, giving it the id passed to it as an argument
var model = new Account({id:id});
console.log("<---------profile router-------->");
// You are instantiating a new view with a fresh model, but its data has
// not yet been fetched so the view will not display properly
this.changeView(new ProfileView({model:model}));
// You are fetching the data here. It will be a little while while the request goes
// from your browser, over the network, hits the server, gets the response. After
// getting the response, this will fire a 'sync' event which your view can use to
// re-render now that your model has its data.
model.fetch();
}
So if you want to ensure your view is updated after the model has been fetched there are a few ways you can do that: (1) pass a success callback to model.fetch() (2) register a handler on your view watches for the 'sync' event, re-renders the view when it returns (3) put the code for instantiating your view in a success callback, that way the view won't be created until after the network request returns and your model has its data.
So I have a page in which a user is selecting from a list of available options via checkboxes.
I have 3 collections: One for possible list of options, one for the currently saved options, and a clone of the saved options. I am using the clone list to add/remove options as they click on checkboxes.
var possibleOptions = new Backbone.Collection("/options");
var currentUserOptions = new Backbone.Collection("/useroptions", { id: 2 });
var clonedUserOptions = new Backbone.Collection(currentUserOptions.toJSON());
The reason this approach was taken is that a user can cancel out of the options page mid edit so want the options persisted upon clicking a save button. The clonedOptions are updated correctly as options are checked/unchecked. However, when I try to update the real list nothing seems to happen.
currentUserOptions.update(clonedUserOptions.toJSON());
My expectation was that backbone would trigger post request for the new models and deletes for each missing model according to the docs (http://documentcloud.github.com/backbone/#Collection-update). Please let me know if I am misunderstanding how this is suppose to work. A simple working example of the right approach would be greatly appreciated.
Thanks,
CF
It is my understand that you have to update the server with individual model calls when the collection changes (as people have mentioned). There are events to cover these changes. However, you can send the entire collection using sync. When each model is added or removed you can flag it as new and deleted and when you are ready to save send the entire collection. Your server methods will have to take care of determining the appropriate add or delete operation then when the collection is sent.
Here is an example of doing a bulk sync. Instead of using this.collection.remove() you may just want to flag as deleted as I mentioned. This is pretty much the only way the server would know what to delete. Technically you could delete everything and then just add what is sent in the bulk update :) Also you might have to do another get or return a collection from the server when you save to update what has actually been removed. I am not sure this helps in your case, but I have used it for pages that "save when done" one button concept.
var one = new model({ id: this.collection.length + 1});
var two = new model({ id: this.collection.length + 2 });
var three = new model({ id: this.collection.length + 3 });
var four = new model({ id: this.collection.length + 4 });
var five = new model({ id: this.collection.length + 5 });
this.collection.add(one.toJSON());
this.collection.add(two.toJSON());
this.collection.add(three.toJSON());
this.collection.add(four.toJSON());
this.collection.add(five.toJSON());
this.collection.sync('update', this.collection, { success: function () { console.log(this.collection.length); } });
this.collection.remove(one);
this.collection.remove(two);
this.collection.sync('update', this.collection, { success: function () { console.log(this.collection.length); } });
And in your case:
currentUserOptions.sync('update', currentUserOptions, { success: function () { //do something } });