Firebase 3-way data binding with ControllerAs syntax

I am trying to get three way data binding using firebase and angularfire. You can see what I have in Plunker: http://plnkr.co/edit/RGA4jZK3Y6n4RkPCHK37

app.js :

angular.module('ideaBattle', ["firebase"]); 

services

 angular .module('ideaBattle') .constant('FBURL', 'https://ideabattle.firebaseio.com/') .service('Ref', ['FBURL', Firebase]) .factory('dataBank', function(Ref, $firebase) { return $firebase(Ref).$asArray(); }); 

controller :

 angular .module('ideaBattle') .controller('ideaListCtrl', displayIdeas); displayIdeas.$inject = ['dataBank']; function displayIdeas(dataBank){ var vm = this; vm.ideas = dataBank; vm.upVote = function(idea){ vm.ideas[idea.id].votes++; }; } 

HTML

 <div ng-controller="ideaListCtrl as vm"> <div ng-repeat="idea in vm.ideas | orderBy: '-votes'"> <div> <h2>{{idea.name}}</h2> <p>{{idea.desc|limitTo: 190}}</p> <span class="btn" ng-click="vm.upVote(idea)">Vote! <span class="badge"> {{idea.votes}}</span></span> </div> </div> </div> 

Version for plunger: http://plnkr.co/edit/RGA4jZK3Y6n4RkPCHK37

What he does is he gets the data from firebase and displays it correctly, but when I click the button to call the upVote function, it only updates locally. I know why it only works locally, but I don't know how to make it also updatable in firebase.

I tried with $ bindTo, but from what I understand requires $ scope to work, and I'm trying to use the "Controller as vm" template without inserting $ scope.

Can someone tell me how to bite this?

+5
source share
3 answers

TL, dr; - 3-way data binding does not work with ControllerAs syntax. The bindTo method requires $scope .

You can use AngularFire with ControllerAs syntax, but you cannot use it with ControllerAs with $bindTo .

$bindTo has a strong dependency on $scope , and it will break without it.

If you need an example using AngularFire with ControllerAs syntax, check out this Plunker demo .

  angular.module('app', ['firebase']) // constant for the Firebase we're using .constant('FBURL', 'https://<your-firebase>.firebaseio.com/todos') // return the Firebase ref as a service .service('Ref', ['FBURL', Firebase]) // return the Todos from Firebase by returning the // array from the factory .factory('Todos', function(Ref, $firebase) { return $firebase(Ref).$asArray(); }) // inject the Todos and assign them to "this" // for the ControllerAs syntax .controller('MainCtrl', function(Todos) { this.todos = Todos; }); 
+10
source

John Papa talks about one goal of using the syntax var vm = this; instead of $scope in each controller, to make the use of $scope conscious choice. In this case, we need to enable $ scope.

I took David East-plunkr in his response and played a little with him. This is not ideal because it depends on the controller. The value is "vm".

http://plnkr.co/edit/vLLaa7QJvfryYRD7cZvO?p=preview

  .controller('MainCtrl', function(Todos, $scope) { /* Add $scope */ var vm = this; vm.todos = Todos.all(); vm.lonelyTodo = Todos.get('-JeNOtYPv7AZmVAoZ1bu'); vm.lonelyTodo.$bindTo($scope, 'vm.lonelyTodo'); /* Add three way binding */ }); 
+5
source

Adding a few clarifications to the answer above, using the ES6 / JS2015 system as an example.

 export class SomeController { constructor($firebaseObject, $scope) { 'ngInject'; //using the firebase SDK 3.0 let obj = $firebaseObject(firebase.database().ref().child('someKey')); // To make the data available in the DOM, assign it to // 'this.data' accessible from DOM as $ctrl.data this.data = obj; // For three-way data bindings, you will still need to inject '$scope' // but you can alias your controller on $scope obj.$bindTo($scope, '$ctrl.data'); // Why does this work? // This works because angular 1x puts controllerAs // on top of $scope. So '$scope.$ctrl.data' is the same as 'this.data'. // Note: $ctrl is the default controllerAs syntax if not specified, // just change $ctrl to your defined controllerAs ailias if // specified. } } 
+1
source

Source: https://habr.com/ru/post/1208607/


All Articles