Routing in Ionic - angularjs

I have an Ionic app where I am calling $http through a factory:
.factory('Articles', function ($http) {
var articles = [];
return {
all: function () {
return $http.get("http://jsonp.afeld.me/?url=http://examplesite.com/page.html?format=json").then(function (response) {
articles = response.data.items;
console.log(response.data.items);
return articles;
});
},
get: function (articleId) {
for (var i = 0; i < articles.length; i++) {
if (articles[i].id === parseInt(articleId)) {
return articles[i];
}
}
return null;
}
}
});
It is working fine and displays a list of articles but when I want to go into a specific article it just shows a blank page even though the url shows the correct article ID. My controller for a single article looks like this:
.controller('MyCtrl', function ($scope, $stateParams, Articles) {
$scope.article = Articles.get($stateParams.articleId);
})
The returned data looks like this (The ID seems to be coming through as a string but using "parseInt" so really not sure what is going on):
0: Object
alias: "title"
attachments: Array[0]
author: Object
category: Object
catid: "67"
created: "2015-04-11 08:06:07"
created_by_alias: ""
events: Object
extra_fields: null
featured: "0"
fulltext: ""
gallery: null
hits: "80"
id: "171"
image: ""
imageLarge: "/url/69bc9c3e85c501b0a6208cc7a55abbf9_L.jpg"
imageMedium: "/url/69bc9c3e85c501b0a6208cc7a55abbf9_M.jpg"
imageSmall: "/url/69bc9c3e85c501b0a6208cc7a55abbf9_S.jpg"
imageWidth: ""
imageXLarge: "/url/69bc9c3e85c501b0a6208cc7a55abbf9_XL.jpg"
imageXSmall: "/url/69bc9c3e85c501b0a6208cc7a55abbf9_XS.jpg"
image_caption: ""
image_credits: ""
introtext: "<p><strong>Mpho Mathoho</strong>lots of text is here....</p>"
language: "*"
link: "/url/title.html"
modified: "2015-06-02 07:44:30"
numOfComments: "0"
numOfvotes: "(0 votes)"
tags: Array[1]
title: "the title"
video: null
video_caption: ""
video_credits: ""
votingPercentage: 0
__proto__: Object

I guess you need to use parseInt() on both fields, change the line:
if (articles[i].id === parseInt(articleId)) {
To:
if (parseInt(articles[i].id) === parseInt(articleId)) {

Related

angular chaining arrays of promises

I am building a website over a database of music tracks. The database is as follows :
music table contains musicid and title
musicrights table contains musicid and memberid
members table contains memberid and memberinfo.
I'm trying to build an array of objects in my database service, which each entry represents a track containing its rightholders (contains information aubout one rightholder but not his name) and their member info (contains name etc). The backend is sailsjs and the code is as follows :
angular.module("myapp").service("database", ["$q", "$http", function($q, $http) {
var database = {};
function getHolderMember(rightHolder) {
return ($http.get("/api/members?where=" + JSON.stringify({
memberid: rightHolder.memberid
})).then(function (res) {
rightHolder.member = res.data[0];
return (rightHolder);
}));
}
function getRightHolders(doc) {
return ($http.get("/api/musicrights?where=" + JSON.stringify({
musicid: doc.musicid
})).then(function(res) {
// array of promises :
// each rightholder of a document has to solve member info
var rightHolders = [];
for (var i in res.data) {
var rightHolder = {
member: res.data[i].memberid,
type: res.data[i].membertype,
rights: res.data[i].memberrights
};
rightHolders.push(getHolderMember(rightHolder));
}
return ($q.all(rightHolders));
}).then(function(rightHolders) {
// expected array of one or two rightholders,
// enriched with member information
// actually returns array of one or two arrays of 30 members
// without rightholder info
console.log(rightHolders);
doc.rightHolders = rightHolders;
return (doc);
}));
}
database.music = function(q) {
return ($http.get("/api/music?where=" + JSON.stringify({
or: [{
title: {
contains: q
}
}, {
subtitle: {
contains: q
}
}]
})).then(function(res) {
// array of 30 promises :
// each one of 30 documents has to resolve its rightholders
var documents = [];
for (var i in res.data) {
documents.push(getRightHolders(res.data[i]));
}
return ($q.all(documents));
}));
}
return (database);
}]);
The first array of promises seems to work as expected, but not the second one in getRightHolders. What is strange is that this function returns an array of one or two promises, which are rightHolders waiting for their memberinfo. But in the callback where I console.log the response, i get an array of one or two (as per the number of pushed promises) but this array's elements are arrays of 30 memberinfo instead of one memberinfo. I don't understand how this $q.all() call gets mixed with the previous-level $q.all.
The data structure is roughly like this
documents [ ] ($http => 30 responses)
music.musicid
music.rightHolders [ ] ($http => 1, 2, 3 responses)
rightholder.rights
rightholder.member ($http => 1 response)
member.memberinfo
Any help appreciated. Thank you !
UPDATE : Thank you for your answer, it worked like a charm. Here's the updated code, with also the migrate service which formats data differently (there is some database migration going on). I kept it out of the first example but your answer gave me this neat syntax.
angular.module("myApp").service("database", ["$q", "$http", "migrate", function($q, $http, migrate) {
var database = {};
function getHolderMember(rightHolder) {
return ($http.get("/api/members?where=" + JSON.stringify({
memberID: rightHolder.member
})).then(function(res) {
return (migrate.member(res.data[0]));
}).then(function(member) {
rightHolder.member = member;
return (rightHolder);
}));
}
function getRightHolders(doc) {
return ($http.get("/api/rightHolders?where=" + JSON.stringify({
musicID: doc.musicID
})).then(function(res) {
return (
$q.all(res.data
.map(migrate.rightHolder)
.map(getHolderMember)
)
);
}).then(function(rightHolders) {
doc.rightHolders = rightHolders;
return (doc);
}));
}
database.music = function(q) {
return ($http.get("/api/music?where=" + JSON.stringify({
or: [{
title: {
contains: q
}
},
{
subtitle: {
contains: q
}
}
]
})).then(function(res) {
return (
$q.all(res.data
.map(migrate.music)
.map(getRightHolders)
)
);
}));
}
return (database);
}
I'm not quite sure how you're getting the result you describe, but your logic is more convoluted than it needs to be and I think this might be leading to the issues you're seeing. You're giving the getRightsHolders function the responsibility of returning the document and based on your comment above, it sounds like you previously had the getHolderMember() function doing something similar and then stopped doing that.
We can clean this up by having each function be responsible for the entities it's handling and by using .map() instead of for (please don't use for..in with arrays).
Please give this a try:
angular
.module("myapp")
.service("database", ["$q", "$http", function($q, $http) {
var database = {};
function getHolderMember(memberId) {
var query = JSON.stringify({ memberid: memberid });
return $http.get("/api/members?where=" + query)
.then(function (res) {
return res.data[0];
});
}
function populateRightsHolderWithMember(rightsHolder) {
return getHolderMember(rightsHolder.memberid)
.then(function (member) {
rightsHolder.member = member;
return rightsHolder;
});
}
function getRightHolders(doc) {
var query = JSON.stringify({ musicid: doc.musicid });
return $http.get("/api/musicrights?where=" + query)
.then(function(res) {
return $q.all(res.data.map(populateRightsHolderWithMember));
});
}
function populateDocumentWithRightsHolders(document) {
return getRightsHolders(document)
.then(function(rightsHolders) {
document.rightsHolders = rightsHolders;
return document;
});
}
database.music = function(q) {
return $http.get("/api/music?where=" + JSON.stringify({
or: [{
title: {
contains: q
}
}, {
subtitle: {
contains: q
}
}]
})).then(function(res) {
return $q.all(res.data.map(populateDocumentWithRightsHolders));
});
}
return (database);
}]);

AngularJS Service losing values between routing

I have 2 different controllers accessing the same service. One of the controllers, search.ctrl.js is visible on every page (the search bar at the top of the page) and the other controller is for a specific partial which displays the results of the search in a table.
The problem that I am having is that the service is setting the values properly after the search form is submitted, and those values are passed back to the controller properly, but then when I call $location.path('/'); the values are no longer set in the service.
Whether this is the correct method or not, all I want is to be able to have a search bar on every page which uses the same html/js/css code, and the results of the search can be accessed from a particular page. Feel free to suggest alternative solutions, but my preferred answer would be one that fixes this one because I have read that it is usually best to use services for sharing data between views.
When viewing the following code keep in mind that it is the documents which I am wanting to access from multiple views.
Cheers :)
Controllers
search.ctrl.js
angular.module("app").controller("SearchController",
function($scope, $location, DocumentSearch){
$scope.title = "Some title";
$scope.doctypes = [
{type: "doc", checked: true},
{type: "docx", checked: true},
{type: "xls", checked: true},
{type: "xlsx", checked: true},
{type: "txt", checked: true}];
$scope.checkAll = true;
$scope.searching = false;
$scope.showSearchPanel = function(){
$scope.searching = !$scope.searching;
};
$scope.checkOrUncheckAll = function(checkAll){
$scope.checkAll = checkAll;
setValueOfAllCheckBoxes($scope.checkAll);
};
$scope.someSelected = function (doctypes) {
for (var d in doctypes){
console.log(doctypes[d]);
if (doctypes[d].checked)
return true;
}
return "You must select a checkbox";
};
$scope.search = function(documentTitle, checkAll){
if (atLeastOneCheckBoxIsSelected()){
$scope.error = null;
$scope.documents = DocumentSearch.search(documentTitle,
getSelectedCheckBoxes());
$location.path("home");
} else {
$scope.documents = null;
$scope.error = "Please select at least one file type.";
}
};
function setValueOfAllCheckBoxes(isChecked){
for (var d in $scope.doctypes){
$scope.doctypes[d].checked = isChecked;
}
}
function atLeastOneCheckBoxIsSelected(){
return (getSelectedCheckBoxes().length > 0);
}
function getSelectedCheckBoxes(){
return $scope.doctypes.filter(function(obj){
return obj.checked;
});
}
});
main.ctrl.js
angular.module("app").controller("MainController",
function($scope, $location, DocumentSearch){
$scope.documents = DocumentSearch.documents;
console.log(DocumentSearch);
});
search.ser.js
angular.module("app").factory("DocumentSearch", function(){
var search = function(title, doctypes){
return searchExample(title, doctypes);
};
function getDocumentExtention(checked){
checked.sort( function(){ return 0.5 - Math.random(); } );
return checked[0].type;
}
console.log("SOMETHING");
var documents = searchExample("Example document", [{type: "txt", checked: true}]);
function searchExample(title, doctypes){
documents = [];
for (var i = 0; i < 50; i++) {
documents.push({
documentTitle: title + " " + i + "." + getDocumentExtention(doctypes),
documentID: i * 111111111,
documentStatus: "Available",
documentVersionDate: "15:32:254 18/11/2015",
documentFileModified: "15:35:974 18/11/2015",
documentCheckedOutUserID: "8276",
documentCheckedOutUsername: "joshuaBrass1"
});
}
return documents;
}
return {
search: search,
documents: documents
};
});

Joining AngularFire paths on a value/key is not working (merging user profiles into records)

I am developing an application with Firebase (1.0) and Angular (1.4). The problem I'm having is to ensure the data in view are synchronised with Firebase, while fetching denormalised data coming from two tables in Firebase:
The book table looks like this:
books:
-JyDpkQrUozE3L7flpo: {
title: "title1",
author: {-JyDpkQrUozE3L7fl1x: true}
},
-JyDpkQrUozE3L7flp1: {
title: "title2",
author: {-JyDptrrrezE3L7flKx: true}
},
-JyDpkQrUozE3L7flp2: {
title: "title3",
author: {-JyDpkQrUozE3L7f222: true}
}
The author table looks like this:
authors:
-JyDpkQrUozE3L7flKx: {
firstname: "jacques",
lastname: "smith"
},
-JyDptrrrezE3L7flKx: {
firstname: "bill",
lastname: "halley"
},
-JyDpkQrUozE3L7f222: {
firstname: "john",
lastname: "ford"
}
My controller looks like this:
.controller('booksController', ['$scope', '$firebaseArray', function($scope, $firebaseArray) {
var ref = new Firebase("https://[PATH].firebaseio.com/";
$scope.bookList = $firebaseArray(ref.child('books'));
$scope.authorList = $firebaseArray(ref.child('authors'));
$scope.getAuthor = function(id) {
return $scope.authorList.$getRecord(id);
};
});
And my html looks like this:
<pre>
<p ng-repeat="book in books" ng-init="author = getAuthor(book.author)">
The author of {{book.title}} is {{author.firstName}} {{author.lastName}}.
</p>
</pre>
The desired output of the above should be: "The author of title1 is Jacques Smith. The author of title2 is Bill Halley ...". What I'm getting however is: "The author of title 1 is. The author of title2 is..." So the author in my html returns a blank.
Any idea?
What I see is that your json data for books has author as an object. This is what is passed into the $getRecord method.The ID of the author is a key, not a value.
I believe if you structure your data like this:
books: {
-JyDpkQrUozE3L7flpo: {
title: "title1",
author: "-JyDpkQrUozE3L7fl1x"
}
-JyDpkQrUozE3L7flp1: {
title: "title2",
author: "-JyDptrrrezE3L7flKx"
},
-JyDpkQrUozE3L7flp2: {
title: "title3",
author: "-JyDpkQrUozE3L7f222"
}
It should work, but it has been a long time since I have used firebase.
Brandon's answer is technically-correct answer to the posed question. I'm going to elaborate a bit on what would be a better way to join these records.
I've actually answered this exact question in a fiddle, and also provided a more sophisticated, elegant, and simpler solution of how to cache and merge user profiles into objects. I'll reiterate the details of how this works here.
app.factory('NormalizedPosts', function($firebaseArray, userCache) {
var PostsWithUsers = $firebaseArray.$extend({
// override $$added to include users
$$added: function(snap) {
// call the super method
var record = $firebaseArray.prototype.$$added.call(this, snap);
userCache.$load( record.user ).$loaded(function( userData ) {
record.userData = userData;
});
// return the modified record
return record;
}
});
return PostsWithUsers;
});
Here I've decided to use a cached list of users, since they are likely to be highly redundant, and this provides an elegant way to keep everything in sync. It's not strictly necessary--we could look them up right there in $$added, but that leaves some edge cases to be handled. So a cache of synchronized users feels right here.
So here's the caching utility:
app.factory('userCache', function ($firebase) {
return function (ref) {
var cachedUsers = {};
// loads one user into the local cache, you do not need to
// wait for this to show it in your view, Angular and Firebase
// will work out the details in the background
cachedUsers.$load = function (id) {
if( !cachedUsers.hasOwnProperty(id) ) {
cachedUsers[id] = $firebaseObject(ref.child(id));
}
return cachedUsers[id];
};
// frees memory and stops listening on user objects
// use this when you switch views in your SPA and no longer
// need this list
cachedUsers.$dispose = function () {
angular.forEach(cachedUsers, function (user) {
user.$destroy();
});
};
// removes one user, note that the user does not have
// to be cached locally for this to work
cachedUsers.$remove = function(id) {
delete cachedUsers[id];
ref.child(id).remove();
};
return cachedUsers;
}
});
And here's a gist putting it all together.
Note that, if we know that when our controller is destroyed, that the data will no longer be useful, we can clean up the listeners and memory by calling $destroy. This isn't strictly necessary and could be a premature optimization, but is probably worth mentioning for users with complex production apps that have tens of thousands of records to track:
app.controller('...', function(NormalizedPosts, userCache, $scope) {
$scope.posts = new NormalizedPosts(<firebase ref>);
$scope.$on('$destroy', function() {
$scope.posts.$destroy();
userCache.$dispose();
});
});
I realize this is an old question but I thought I share my solution for those who are still googling.
Like Brandon mentions you shouldn't have the auther as an object, just and ID (reference)
Your data should look like this:
{
books: {
JyDpkQrUozE3L7flpo: {
title: "title1",
authorId: JyDpkQrUozE3L7fl1x
},
JyDpkQrUozE3L7flp1: {
title: "title2",
authorId: JyDptrrrezE3L7flKx
},
JyDpkQrUozE3L7flp2: {
title: "title3",
authorId: JyDpkQrUozE3L7f222
}
},
authors: {
JyDpkQrUozE3L7flKx: {
firstname: "jacques",
lastname: "smith"
},
JyDptrrrezE3L7flKx: {
firstname: "bill",
lastname: "halley"
},
JyDpkQrUozE3L7f222: {
firstname: "john",
lastname: "ford"
}
}
}
Note that I changed the author to authorId to be more explicit what is a authoer object and what is just the id. Now lets get all the books and the author.
app.factory('BooksWithAuthor', function($firebaseArray, $firebaseObject) {
const books = firebase.database().ref('books')
const authors = firebase.database().ref('authors');
const bookList = $firebaseArray.$extend({
$$added: function(snap) {
const book = $firebaseArray.prototype.$$added.call(this, snap);
book.author = $firebaseObject(authors.child(book.authorId));
return record;
}
});
return new bookList(books)
});
app.controller('BookCtrl, function(BooksWithAuthor) {
$scope.BookList = BooksWithAuthor;
});
And then in your HTML just do
<div ng-repeat="book in booklist">
{{ book.title }} was written by {{ book.author.firstname }} {{ book.author.lastname }}
</div>

Angular Resource update method with an array as a parameter

I have been googleing this for a few weeks with no real resolution.
I am sure someone will mark this a duplicate, but I am not sure it really is, maybe I am just being too specific, anyway here goes.
I am using angular in a node-webkit app that I am building. I have an api built in express and I am using MongoDB (#mongolab) with Mongoose for the DB.
I had this working fine as long as all of the data types were simple strings and numbers. but I had to restructure the data to use arrays and complex objects. After restructuring the data I was able to get post API calls to work fine, but I cannot get my PUT calls to work at all.
The data looks like this:
itemRoles was an array, but I thought it was throwing the error I am getting now, so I converted it back to a string.
itemStats is causing the problem. Angular is looking for an object, but itemStats is an array (I think anyway). itemStats used to be a string as well, but its easier to work with in my view if it is an array of objects with key:value pairs, which is why I altered it.
I should note I am new to MongoDB as well, first time using it.
{
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bd8"
},
"itemRoles": "healer,dps",
"itemRating": 192,
"itemName": "Advanced Resolve Armoring 37",
"itemClass": "consular",
"itemLevel": 69,
"itemStats": [
{
"name": "Endurance",
"value": 104,
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bda"
}
},
{
"name": "Willpower",
"value": 124,
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bd9"
}
}
],
"__v": 0
}
The Mongoose Schema looks like this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//var stats = new Schema({
//name: String,
//value: Number
//});
var armoringSchema = new Schema({
itemType: String,
itemClass: String,
itemRoles: String,
itemLevel: Number,
itemName: String,
itemRating: Number,
itemStats: [{ name:String, value:Number}]
});
module.exports = mongoose.model('Armor', armoringSchema);
Express API Route:
/ on routes that end in /armors/:id
// ----------------------------------------------------
router.route('/armors/:id')
// get method omitted
// update the armoring with specified id (accessed at PUT http://localhost:8080/api/armors/:id)
.put(function(req, res) {
// use our armor model to find the armor we want
Armoring.findById({_id: req.params.id}, function(err, armor) {
if (err) {
return res.send(err);
}
for(prop in req.body) {
armor[prop] = req.body[prop];
}
// save the armor
armor.save(function(err) {
if (err) {
return res.send(err);
}
res.json({success:true, message: 'Armor updated!' });
});
});
})
Resource Factory:
swtorGear.factory('armoringFactory', ['$resource', function ($resource) {
return $resource('http://localhost:8080/api/armors/:id', {}, {
update: { method: 'PUT', params: {id: '#_id'}},
delete: { method: 'DELETE', headers: {'Content-type': 'application/json'}, params: {id: '#_id'}}
});
}]);
Route for editing:
.when('/edit/armor/id/:id', {
templateUrl: 'views/modelViews/newArmor.html',
controller: 'editArmorCtrl',
resolve: {
armoring: ['$route', 'armoringFactory', function($route, armoringFactory){
return armoringFactory.get({ id: $route.current.params.id}).$promise;
}]
}
})
Contoller (just the save method, the first part of the controller populates the form with existing data):
$scope.save = function(id) {
$scope.armor.itemStats = [
$scope.armor.stats1,
$scope.armor.stats2
];
$scope.armor.itemRoles = '';
if($scope.armor.role.tank) {
$scope.armor.itemRoles += 'tank';
}
if($scope.armor.role.healer) {
if($scope.armor.itemRoles != '') {
$scope.armor.itemRoles += ',healer';
} else {
$scope.armor.itemRoles += 'healer';
}
}
if($scope.armor.role.dps) {
if($scope.armor.itemRoles != '') {
$scope.armor.itemRoles += ',dps';
} else {
$scope.armor.itemRoles += 'dps';
}
}
console.log($scope.armor);
$scope.armor.$update(id)
.then(function(resp) {
if(resp.success) {
var message = resp.message;
Flash.create('success', message, 'item-success');
$scope.armors = armoringFactory.query();
} else {
var message = resp.message;
Flash.create('success', message, 'item-success');
}
});
}
Formatted data being sent via PUT method (from console.log($scope.armor) ):
Error on save:
I haven't seen nesting schemas in the way that you're doing it. Here's something to try (hard to say if this is it for sure, there's a lot going on):
var armoringSchema = new Schema({
itemType: String,
itemClass: String,
itemRoles: String,
itemLevel: Number,
itemName: String,
itemRating: Number,
itemStats: [{
name: String,
value: Number
}]
});
Also we need to pass in an object to $update instead of just a number. Change $scope.armor.$update(id) to $scope.armor.$update({id: id}).

Joining data between paths based on id using AngularFire

I am currently working on an app using firebase and angularJS (ionic). Basically this is a car management app, so you have people sharing their cars with others. I tried to structure the data as flat as possible to be efficient. My issue here is that if without problem I can display the list of the car_id of the different cars shared with the logged user, I can't find a way to display the list of cars shared with the user displaying the year and the model.
Thank you in advance for your help !
{
"rules": {
"users": {
".write": true,
"$uid": {
".read": "auth != null && auth.uid == $uid"
},
"cars": {
"car_id":true,
"role":true // Owner, borower...
}
},
"cars": {
"car_id":true,
"model":true,
"year":true
}
}
}
carapp.controller("carsController", function($scope, $firebaseObject, $ionicPopup, $ionicHistory) {
$ionicHistory.clearHistory();
$scope.list = function() {
frbAuth = frb.getAuth();
if(frbAuth) {
var userObject = $firebaseObject(frb.child("users/" + frbAuth.uid));
userObject.$bindTo($scope, "user");
$scope.cars = frb.child("cars");
}}
$scope.createCar = function() {
$ionicPopup.prompt({
model: 'Create a new car',
inputType: 'text'
})
.then(function(result) {
if(result !== "") {
var newCar = $scope.cars.push({
model: result
})
var newCarId = newCar.key();
$scope.user.cars.push({car_id: newCarId, role: "owner" });
} else {
console.log("Action not completed");
}
});
}
});
<div class="list">
<a ng-repeat="car in user.cars" >
<h2>{{car.car_id}}</h2> ----> works fine !
<h2>{{car.model}}</h2> ----> How to get this working ?
<h2>{{car.year}}</h2> ----> How to get this working ?
</a>
</div>
In the users/ path, begin by storing the list of cars by index, instead of in an array. So your structure would be:
{
"users": {
"kato": {
"cars": {
"DeLorean": true
}
}
},
"cars": {
"DeLorean": {
model: "DeLorean",
year: "1975"
}
}
}
To join this using AngularFire, you have several approaches available. An AngularFire-only solution might look like this, taking advantage of $extend:
app.factory('CarsByUser', function($firebaseArray) {
return $firebaseArray.$extend({
$$added: function(snap) {
return new Car(snap);
},
$$updated: function(snap) {
// nothing to do here; the value of the index is not used
},
$$removed: function(snap) {
this.$getRecord(snap.key()).destroy();
},
// these could be implemented in a manner consistent with the
// use case and above code, for simplicity, they are disabled here
$add: readOnly,
$save: readOnly
});
var carsRef = new Firebase(...).child('cars');
function Car(snap) {
// create a reference to the data for a specific car
this.$id = snap.key();
this.ref = carsRef.child(this.$id);
// listen for changes to the data
this.ref.on('value', this.updated, this);
}
Car.prototype.updated = function(snap) {
this.model = data.model;
this.year = data.year;
}
Car.prototype.destroy = function() {
this.ref.off('value', this.meta, this);
};
function readOnly() { throw new Error('This is a read only list'); }
});
app.controller('...', function($scope, CarsByUser, authData) {
// authenticate first, preferably with resolve
var ref = new Firebase(...).child(authData.uid);
$scope.cars = CarsByUser($scope);
});
For a more sophisticated and elegant approach, one could utilize NormalizedCollection and pass that ref into the AngularFire array:
app.controller('...', function($scope, $firebaseArray) {
var ref = new Firebase(...);
var nc = new Firebase.util.NormalizedCollection(
ref.child('users/' + authData.uid),
ref.child('cars')
)
.select('cars.model', 'cars.year')
.ref();
$scope.cars = $firebaseArray(nc);
});

Resources