【问题标题】:A little clarity on getting key values using AngularFire v2?使用 AngularFire v2 获取关键值有点清晰?
【发布时间】:2013-12-15 17:37:04
【问题描述】:

很抱歉这篇文章太长了,但这让我有点抓狂:

假设我想在加载时获取项目的“标题”和“.priority”键值。

首先让我们看看每个东西是如何布置的:

 $scope.items = $firebase(new Firebase("https://****.firebaseio.com"));

 $scope.items.$on('loaded', function() { 

console.log($scope.items);

});

我们得到:

> Object {$bind: function, $add: function, $save: function, $set: function, $remove: function…}
    > $add: function (item, cb) {
    > $bind: function (scope, name) {
    > $child: function (key) {
    > $getIndex: function () {
    > $on: function (type, callback) {
    > $remove: function (key) {
    > $save: function (key) {
    > $set: function (newValue) {

    > this is my item: Object
          $$hashKey: "012"
          $id: "this is my item"
          $priority: 2884707
          title: "this is the title of my item"
          __proto__: Object


    > __proto__: Object

看起来不错,让我们尝试获取 $priority:

 console.log($scope.items.$child('$priority'));

哎呀:

Uncaught Error: Firebase.child failed: First argument was an invalid path: "$priority". Paths must be non-empty strings and can't contain ".", "#", "$", "[", or "]"

好的,我们现在先跳过它,试试标题:

console.log($scope.items.$child('title'));

> Object {$bind: function, $add: function, $save: function, $set: function, $remove: function…}
    > $add: function (item, cb) {
    > $bind: function (scope, name) {
    > $child: function (key) {
    > $getIndex: function () {
    > $on: function (type, callback) {
    > $remove: function (key) {
    > $save: function (key) {
    > $set: function (newValue) {
    > __proto__: Object

没有标题。

好的,让我们换一种方式试试吧:

    var firstItem = $scope.items.$getIndex()[0];  //returns $ids in order of priority
     console.log($scope.items.$child(firstItem));

     > Object {$bind: function, $add: function, $save: function, $set: function, $remove: function…}
         > $add: function (item, cb) {
         > $bind: function (scope, name) {
         > $child: function (key) {
         > $getIndex: function () {
         > $on: function (type, callback) {
         > $remove: function (key) {
         > $save: function (key) {
         > $set: function (newValue) {
              title: "this is the title of my item"
         > __proto__: Object

但是现在没有优先级了!

厨房水槽对着电脑发誓:

 console.log($scope.items.title);

     > undefined

 console.log($scope.items[0].title);

     > Uncaught TypeError: Cannot read property 'title' of undefined 

  console.log(Object.keys($scope.items));     

     > ["$bind", "$add", "$save", "$set", "$remove", "$child", "$on", "$getIndex"]

我错过了什么?我可以通过掉头来获得“标题”,(使用“$getIndex()”找出项目的 $id 是什么,抓住第 n 个项目,然后使用“$child()”进行另一个调用),但即使这样也不适用于 $priority。有没有更简单的方法从 AngularFire v2 中获取关键值?或者有什么方法可以获得 $priority?

【问题讨论】:

  • 这里有两件事。第一个是 $child 会收到一个记录的键,所以你想尝试像$scope.items.$child('record1').$priority 这样的东西。其次,请尝试升级到latest/official 0.5 release,因为 Anant 刚刚做了一些可能适用于此的修复。如果没有帮助,请报告您的发现。
  • 这是我要链接的版本,'$scope.items.$child('record1').$priority' 给了我'undefined',这是正确的,因为没有返回 $priority当使用 'console.log($scope.items.$child('record1'))' 时,如我的“好吧,让我们以不同的方式尝试”示例。如果应该这样,那可能是一个错误。
  • 我不清楚。关键是 $child 的操作就像 Firebase.child()。 angularFire 转到 Firebase,在当前路径上调用 .child(),并为该子路径返回一个新的 $firebase 对象。因此,您不能要求 $child('$priority') 因为这不是有效的 Firebase 密钥。这不是从对象获取子键的方法,而是对 Firebase 路径的新同步引用。因此,将使用$scope.items['$priority'] 或类似的方式获得子密钥(我在上面写错了——对不起)。
  • 对不起,如果我误解了,但 console.log( $scope.items.$child('the_id').$child('title')) 工作正常,但 console.log( $scope.items.$child('the_id')['$priority']) 返回“未定义”,console.log($scope.items['$priority']) 也是如此。这是意料之中的,因为console.log( $scope.items.$child('the_id')) 不会像console.log( $scope.items) 对每个对象那样返回$$hashkey、$priority 或$id。这让我想知道这是否是一个错误。
  • 很可能是一个错误,很难说,因为我还没有完全理解。但是 $child('$priority') 永远不会起作用,因为 Firebase 路径键中不允许使用 $。这是解决此问题的第一步,即准确了解 $child 的作用,即返回一个全新的 $firebase 引用(不仅仅是数据中给定键的值)

标签: firebase angularfire


【解决方案1】:

我相信我/正在经历同样的问题。希望这与您的经历有关。即:

$scope.items = $firebase(new Firebase("https://xxxxxx.firebaseio.com"));
$scope.items.$on('loaded', function() {
  console.log($scope.items['some key']); // this writes undefined to console
});

我注意到的是,如果我不依赖 loaded 事件,这实际上确实有效。例如在 HTML 中:

<a href="#" data-ng-click="logItem()">click me</a>

在 JS 中:

$scope.items = $firebase(new Firebase("https://xxxxxx.firebaseio.com"));
$scope.logItem = function() {
  console.log($scope.items['some key']); // this works
}

单击“单击我”链接按预期将我的项目记录到控制台。

感觉loaded 时间的集合没有完全填充来自 firebase 的基础项目。

【讨论】:

  • 顺便说一句,我现在使用this answer 中定义的模式。事实证明,虽然在 loaded 时间未填充原始 firebase 数据,但它作为参数传递给回调函数,因此您可以根据需要以这种方式访问​​它。
【解决方案2】:

$child 方法只能用于创建 AngularFire 引用。调用$child 与调用$firebase(new Firebase(parentULR + "/childName")) 相同。在您的示例中,如果您要做的只是获取给定对象的 $prioritytitle,您可以简单地执行以下操作:

$scope.items = $firebase(new Firebase("https://****.firebaseio.com"));
$scope.items.$on('loaded', function() {
  var item = $scope.items['your-item-id'];
  console.log(item['$priority']);
  console.log(item.title);
});

如果您不知道您的项目的 ID,您可以遍历 $scope.items 对象以找到它。

【讨论】:

  • 谢谢,但是当我这样做时会发生这种情况:imgur.com/a/mXePx(对不起,这是向您展示的最快方式,我显然编辑了 firebase 地址,但仅此而已)。
  • 这很奇怪,你能 console.log($scope.stories) 吗?它应该有一堆对象。
  • mlenner up there 想通了,显然它还没有准备好 $on('loaded'),所以我所要做的就是使用一点 $timeout。
  • 我觉得你不应该这样做。如果值是loaded,那么它确实应该作为回调空间。不应该额外需要用$timeout 包装它。或者使用回调中的值。坦率地说,无论如何,我觉得回调对人们来说更自然。 $scope.items.$on('loaded', function(value) {console.log(value)});
  • 是的,这似乎是一个错误。我们应该将加载的回调包装在它自己的小 $timeout 中。
【解决方案3】:

正如您所指出的,您的示例有些零散,也没有可以使用的数据结构示例。所以很难对你想要完成的事情有一个清晰的了解。我将在下面对所有这些事情做出一些假设,然后相应地提供一个工作示例。如果这不能回答问题,也许它会帮助我们深入挖掘并找到您正在寻找的确切用例。

首先,假设我们在 kato.firebaseio.com/users 上有一个用户列表,每个用户都是一个像这样的对象:

/users/:id/name
/users/:id/email
/users/:id/favorite_dessert

现在,假设我想使用以下 angularCode 使这些工作:

<ul>
  <li ng-repeat="user in users">{{user.name}} really likes {{user.favorite_dessert}}</li>
</ul>

在我的控制器中,我可以这样写:

var fbRef = new Firebase('https://kato.firebaseio.com/users');
$scope.users = $firebase( fbRef );

现在它们会自动出现在我的 HTML 代码中。

现在,假设当其中一个用户被点击时,我想获得一个双向绑定,可以像这样编辑它:

<form ng-controller="EditUserController">
      <input ng-model="user.name" type="text" />
      <input ng-model="user.email" type="text" />
      <input ng-model="user.favorite_dessert" type="text" />
</form>

EditUserController里面我可以得到用户如下:

var fbRef = new Firebase('https://kato.firebaseio.com/users/'+user_id);
$firebase( fbRef ).$bind($scope, 'user');

或者我可以像这样使用$child(纯粹是为了演示$child的用法,没有必要):

var fbRef = new Firebase('https://kato.firebaseio.com/users');
// $child gives a new $firebase object! not a ref to a hash key!
$firebase( fbRef ).$child( user_id ).$bind($scope, 'user');

如果我想在我的控制器中以编程方式访问这些数据,我可以这样做:

var fbRef = new Firebase('https://kato.firebaseio.com/users');
var usersRef = $firebase( fbRef );
var userId = 'kato';
usersRef.$on('loaded', function() {
   if( usersRef.hasOwnProperty(userId) ) {
      // note that we just grab it by key; not $child!
      var userRecord = usersRef[userId]; 
      console.log(userId + ' was found, name is ' + userRecord.name + ' and priority is ' + userRecord['$priority']);
   }

});

【讨论】:

  • 抱歉 Kato - 我花了几个小时试图重新创建它,但 myRef[blah]myRef.blah 总是返回未定义。 myRef.$child('blah') 有效,但受到限制,因为就像你说的那样,它不能返回任何带有“$”的东西。我不知道这与 AngularFire 有多大关系,我会把它带到他们的 github 上,看看他们对缺少的 $priority 有什么看法。但这里有一个功能请求:startAt(fbRef.getIndex()[100])(是的,这一切都是关于尝试 startAt() firebase 中的第 n 个项目!我的设置方式并不容易弄清楚 $id 和 $priority)一如既往地感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-16
  • 1970-01-01
  • 2019-08-11
  • 1970-01-01
  • 2017-06-03
  • 2012-10-21
相关资源
最近更新 更多