Unique AngularFire calls in Angular template functions - angularjs

I'm using AngularFire and have an ng-repeat list with items that contain data specific to the "author" of that item (multiple users can add to the list), such as name, location, etc. I'm not writing that data into the array being iterated over by ng-repeat since it could change in the future. Instead, that author-specific data is store in a different location so the goal is that if the author changes their information, all of it is reflected in the list.
For a contrived example, imagine I'm iterating over a list of books from different authors. That list will contain the book-specific data (such as title, publish date, etc.) but I will also want to display the author's information in the list. Instead of including the author's information directly within the book data, I want to simply reference that author ID, and pull in whatever data is in their profile so if they change their name, it'll reflect the changes in all of their book listings.
That means I'm left to make async calls to Firebase to retrieve that information for each list item via a template function, such as {{getAuthorName(authorId)}}. The only problem is that they're async calls and the template function evaluates before the data is available.
I've looked into how to accomplish but have yet to find a solution that accommodates what I need. The answers here seem close, but they appear to no longer work in Angular >= 1.2.0 and they don't account for having to return different data for each template function call.
Update
Here is a JSFiddle with what I have now. I've made some progress, but all that's being returned now is the promise object as expected. I'm not sure how to implement .then in this scenario to get the actual value.
Any help would be great.

You can make use of $firebaseObject and then store that in an object to make sure it doesn't get hit again. like so:
var authors = {};
$scope.getAuthorName = function(authorId){
if(!authors[authorId]){
var authorRef = new Firebase(fburl + "/authors/" + authorId);
authors[authorId] = $firebaseObject(authorRef);
}
return authors[authorId];
};
You can see the working fiddle here: http://jsfiddle.net/0rcdpq47/

Related

Search if ID is on an array in another collection in mongo with mongoose and angular

So, I have a collection called users where I store the user data like password, username and so on, and then I have another collection called couples where I store inside an array of the users who are in that couple.
In the angular page I want to check if the current user logged in has a couple, so I search for its ID in the couples collection like this:
$scope.couples = Couples.query({
members: $scope.authentication.user._id
});
This return the couple info if the user ID is found in a couple in the couples collection.
The problem is that I get in my scope an array and I can't figure it out how to access the data inside that array (inside the array is the object with the couple information).
So in the $scope.couple if I print the value I get everything in console, but $scope.couple[0].members fails or $scope.couple.members fails.
If a go to the network usage I see a call to couples that returns the info in a json, but I can't understand why is an array in my scope.
Thanks

ng-repeat convert resource objects to simple objects

Iam getting my data with help of the Angular's $resource service as array. Each element of that array is an Resource-Object. So i can use methods like $save and $update of these Objects. In a view i represent my array with the help of the ng-repeat directive like:
<div ng-repeat="appointment in object.appointments" ng-click="editAppointment(appointment)">
And here i get in trouble. The appointment-Object i get in the editAppointment-Method is a simple Object. No Resource Object anymore. So i cant use the helpfull methods like i mentioned above.
$scope.editAppointment= function(appointment){
console.log(appointment); // > Object
console.log(object.appointments); // > Array of Resource
}
Have somebody noticed that problem too? May its a bug, but i cant imagine that.
Assuming your resource class is called Appointment, you should just be able to do:
$scope.editAppointment= function(appointment){
new Appointment(appointment).save();
}
Presumably your Appointment resource looks something like the following (i.e. it correctly maps some sort of id property from existing objects to the URL parameters):
var Appointment = $resource('/appointment/:appointmentId', {appointmentId:'#id'});
This would be the case if your appointment objects (i.e. the underlying JSON objects handled by your API) have an ID property called id. If it's called something else (or if there are multiple path variables in your URL) you'll just need to change the second argument to map all of the properties of the objects being saved (the values starting with '#') to the URL path variables (the things starting with ':' in your URL).
See where they save a new card in the credit card example here: http://docs.angularjs.org/api/ngResource.$resource. The fact that they're dealing with a totally new object and that you're trying to save an existing one is irrelevant. Angular doesn't know the difference.

Access a collection from a different router/view

I'm still kind of new to Backbone, and I'm pretty stumped by this...
I have a router/collection/view for Titles, and a router/collection/view for Campaigns.
When a user creates a new campaign, it must be associated with a title. So in the create form, I need to access the list of all titles so I can get their names and (rails) IDs.
I'm not sure how to access this title list from within my Campaigns view though.
A few thoughts on solutions:
Using an association library like ligature -- this seems like a lot of work for a fairly straightforward problem, and I don't really need associations.. I just need the full list of titles.
Declaring my Titles collection in the global scope and passing it to the initializer of the Titles router.
Create a Titles collection in the Campaigns router.. this seems pretty redundant.
Happy to post code, but I don't know what is relavent.
If by global scope you mean window, I'd recommend avoiding that if possible. Do your Titles / Campaign classes have access to a shared scope? E.g.:
( function () {
var App = {};
// ...
// Titles code
var titles = App.titles = new Backbone.Collection;
// ...
// Campaign code
var titles = App.titles;
} )();
You might want to arrange things so the various parts of your app have access to a shared scope like that if you want to have a single Titles collection used throughout the app.
Otherwise if that's impractical or undesirable for some reason, you could just create a separate Titles collection in your Campaigns section and fetch it from the server, or bootstrap it, or however you want to populate it.
It's hard to be more specific without seeing some code, so maybe this will suggest some code that you think would be relevant to post.

How to populate a Backbone.js collection's _byId array so that I can use `get` on it?

I have a collection, and the collection.models returns an array of models. However, when I call collection.get(someId) (and this id is the id of the model that is in the collection.models array), I get undefined. Looking at collection._byId, it looks like an empty object.
How do I properly populate _byId, so that I can use get? Or perhaps I'm doing something wrong when initializing my collection, which is why _byId is empty.
I'm a little late, but hopefully this is still useful to some other people.
Collection._byId is just a normal js hash object. There's really nothing fancy about it. If you want Collection.get to work, just add all the models into the _byId hash.
Inside the collection's scope:
var someId = '123'; // any id will do
this._byId[someId] = someModel; // someModel.id = '123'
console.log(!!this.get(someId)); // should return true
Since I'm using this with Rails, the default json generated by Rails doesn't work well with Backbone. I don't know why I didn't see it while trying to learn Backbone. Anyway, you could either:
Change the way Rails generates its JSON
Change the way your Backbone app reads the JSON.
Sounds like the OP had a slightly different problem, but I experienced a similar issue and thought I'd post what worked for me.
Like the original issue, collection.models contained the right model, but in my case, the _byId hash contained a cid version of the model that wasn't empty. Nevertheless, _byId didn't contain a model with normal id (there's usually two version - an id one and a cid one), so I wasn't able to use collection.get(id) to retrieve it. My problem became a bit clearer when I read up about cid. From the docs:
Client ids are handy when the model has not yet been saved to the server, and does not yet have its eventual true id, but already needs to be visible in the UI.
I didn't think it was a problem with waiting for the server as my cid model and the collection.model had the correct ids. However passing in { wait : true } as an option in collection.create fixed this issue for me.

How to get a value from a combobox in a form after the field is populated by the database

I have a formPanel with two of the form items as comboboxes with their stores populated by the database. The value from comboBoxA needs to be used to get the value for comboBoxB however comboBoxA.getValue() (as well as getRawValue()) are returning undefined.
storeA.load();
var comboBoxA = Ext.getCmp(comboBoxAID);
storeB.baseParams.UserID = comboBoxA.getValue();
storeB.load();
As noted in the docs, store loading is asynchronous, so you have to do your additional processing within the appropriate callback:
storeA.on('load', function(){
var comboBoxA = Ext.getCmp(comboBoxAID);
storeB.baseParams.UserID = comboBoxA.getValue();
storeB.load();
});
storeA.load();
Loading a ComboBoxes store does not actually select a value. Try making a selection first (or loading a record into the form, etc). It sounds like your trying to link the 2 combos. If thats the case, search around for a tutorial, there are few out there. This should get you started, Linked Combos.
You might want to try this. It might be exactly what you are looking for. It also has a demo on the same page. The page is in german but the demo is predictable and the code is in english so test this.

Resources