How to associate an input with a user in firebase using angularfire?

angularfire, angularjs, firebase, javascript

Solution

There a couple of things tripping you up.

Differences between `$firebase`and `$firebaseAuth`

AngularFire 0.9 is made up of two primary bindings: `$firebaseAuth` and `$firebase`. The `$firebaseAuth` binding is for all things authentication. The `$firebase` binding is for synchronizing your data from Firebase as either an object or an array.

Inside of `UpdateFirebaseWithString` you are calling `$asArray()` on `$firebaseAuth`. This method belongs on a `$firebase` binding.

When to call `$asArray()`

When you call `$asArray` inside of the `UpdateFirebaseWithString` function you will create the binding and sync the array each time the function is called. Rather than do that you should create it outside of the function so it's only created one item.

Even better than that, you can abstract creation of the binding and the `$asArray` function into a factory.

Plunker Demo

app.factory("Ideas", ["$firebase", "Ref", function($firebase, Ref) {
  var childRef = Ref.child('ideas');
  return $firebase(childRef).$asArray();
}]);

Get the user before the controller invokes

You have the right idea by getting the user from `$getAuth`. This is a synchronous method, the app will block until the user is returned. Right now you'll need to get the user in each controller. You can make your life easier, by retrieving the user in the app's `run` function. Inside of the `run` function we can inject `$rootScope` and the custom `Auth` factory and attach the user to `$rootScope`. This way the user will available to all controllers (unless you override `$scope.user` inside of your controller).

app.run(["$rootScope", "Auth", function($rootScope, Auth) {
  $rootScope.user = Auth.$getAuth();
}]);

This is a decent approach, but as mentioned before `$scope.users` can be overridden. An even better way would be to resolve to user from the route. There's a great section in AngularFire guide about this.

Associating a user with their data

Now that we have the user before the controller invokes, we can easily associate their id with their input.

app.controller("fluttrCtrl", ["$scope", "Ideas", function($scope, Ideas) {
    $scope.ideas = Ideas;
    $scope.idea = "";

    $scope.UpdateFirebaseWithString = function () {     
      $scope.ideas.$add({
        idea: $scope.idea,
         userId: $scope.user.google.id,
      }).then(function(ref) {
        clearIdea();
      });
    };

  function clearIdea() {
    $scope.idea = "";
  }

}]);

Problem

I've built an app with firebase that can login a user and attain their id, but I can't figure out how to incorporate this with a user making a submission of a string. See Code pen here: http://codepen.io/chriscruz/pen/OPPeLg HTML Below: ``` <html ng-app="fluttrApp"> <head> <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script> <script src="https://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script> <script src="https://cdn.firebase.com/js/client/2.0.2/firebase.js"></script> <script src="https://cdn.firebase.com/libs/angularfire/0.9.0/angularfire.min.js"></script> </head> <body ng-controller="fluttrCtrl"> <button ng-click="auth.$authWithOAuthPopup('google')">Login with Google</button> <li>Welcome, {{user.google.displayName }}</li> <button ng-click="auth.$unauth()">Logout with Google</button> <input ng-submit= "UpdateFirebaseWithString()" ng-model="string" ></input> ``` Javascript Below: ``` <script> var app = angular.module("fluttrApp", ["firebase"]); app.factory("Auth", ["$firebaseAuth", function($firebaseAuth) { var ref = new Firebase("https://crowdfluttr.firebaseio.com/"); return $firebaseAuth(ref); }]); app.controller("fluttrCtrl", ["$scope", "Auth", function($scope, Auth) { $scope.auth = Auth; $scope.user = $scope.auth.$getAuth(); $scope.UpdateFirebaseWithString = function () { url = "https://crowdfluttr.firebaseio.com/ideas" var ref = new Firebase(url); var sync = $firebaseAuth(ref); $scope.ideas = sync.$asArray(); $scope.ideas.$add({ idea: $scope.string, userId:$scope.user.google.id, }); }; }]) </script> </body> </html> ``` Also assuming, the above dependencies, the below works to submit an idea, but the question still remains in how to associate this with a user. See codepen here on this: http://codepen.io/chriscruz/pen/raaENR ``` <body ng-controller="fluttrCtrl"> <form ng-submit="addIdea()"> <input ng-model="title"> </form> <script> var app = angular.module("fluttrApp", ["firebase"]); app.controller("fluttrCtrl", function($scope, $firebase) { var ref = new Firebase("https://crowdfluttr.firebaseio.com/ideas"); var sync = $firebase(ref); $scope.ideas = sync.$asArray(); $scope.addIdea = function() { $scope.ideas.$add( { "title": $scope.title, } ); $scope.title = ''; }; }); </script> </body> ```

Original source