Chris
Chris

Reputation: 5834

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

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>

Upvotes: 3

Views: 1089

Answers (1)

David East
David East

Reputation: 32624

There a couple of things tripping you up.

Differences between $firebaseand $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 = "";
  }

}]);

Upvotes: 5

Related Questions