Firebase 3-way data binding with ControllerAs syntax

﹥>﹥吖頭↗ 提交于 2019-12-05 09:43:57

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 can't use it with ControllerAs with $bindTo.

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

If you want an example of 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;
  });

John Papa talks about one of the purposes of using the var vm = this; syntax instead of $scope in every controller is to make the use of $scope a conscious choice. In this case we need to include $scope.

I took David East's plunkr in his answer and fiddled with it a bit. It isn't perfect because it depends on the controllerAs value being '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 */
  });

Adding a few clarifications comments to the response above using ES6/JS2015 systax 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. 
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!