【问题标题】:Using nested ng-repeat to iterate through firebase object in Angularfire 0.8在 Angularfire 0.8 中使用嵌套的 ng-repeat 遍历 firebase 对象
【发布时间】:2014-10-15 06:20:01
【问题描述】:

我的目标:

我有一个需要迭代的列表。此列表中的每个项目都有自己的列表(嵌套)。对于这些嵌套列表项中的每一个,我需要有一组两个复选框供用户指定他们的选择。我需要将这些复选框选项同步回应该与 firebase 同步的范围变量。 以下是我的代码的简化版本。

示例

我的控制器

fbutil.syncObject("items").$bindTo($scope, "items");

我的看法

<div ng-repeat="item in items">
    {{item.title}}

    <div ng-repeat="option in item.options">
        {{option.title}}

        <input type="checkbox" id="{{item.title}}+{{option.title}}+pos" ng-model="option.results" ng-true-value="'positive'" ng-false-value="''"><label for="{{item.title}}+{{option.title}}+pos"></label>

        <input type="checkbox" id="{{item.title}}+{{option.title}}+neg" ng-model="option.results" ng-true-value="'negative'" ng-false-value="''"><label for="{{item.title}}+{{option.title}}+neg"></label>
    </div>
</div>

我的问题

我刚刚从 angularfire 0.7.1 更新到 0.8,并在我认为迭代嵌套的 ng-repeat 时开始出现此错误。它以前工作得很好,但现在当我选择一个复选框时出现错误,说明:

Firebase.set failed: First argument  contains an invalid key ($$hashKey) in property '0.testCustom.0'.  Keys must be non-empty strings and can't contain ".", "#", "$", "/", "[", or "]"

我理解(我认为)这与 Angularfire 将数据作为数组或对象获取有关。我知道这是因为 angular/firebase 将这些键(如 $id 或 $$hashKey)附加到对象并且使用 angular.copy() 清理这些键不起作用。

这里是a similar question,但@kato 的唯一响应不是获取父集合,而是直接转到子集合。 在我的情况下我想不出办法... @kato 在 cmets 中的帖子:

不要将父级 (account/) 作为对象获取,然后尝试将其子级用作集合。嵌入式数组不起作用,因为 Angular 将无效属性附加到它。 [...] AngularFire 是一个绑定库——它绑定对象和集合——而不是 Firebase 数据树的本地副本。直接获取收藏就行了

/////////编辑

针对@jacobawenger 的评论,如果我使用 $asArray() 而不是 $asObject() 来提取我的集合,我将如何将这些更改保存回 firebase?

这是我正在尝试做的事情:

Plunker example

我有一个我不知道如何实现的“saveChange()”函数

【问题讨论】:

  • 正如@kato 在他对另一个线程的回复中所暗示的那样,我们正在远离在深层嵌套结构上使用 $bindTo() 。它效率不高,几乎从来都不是你真正想要的。在这里,不要使用 $asObject() 获取 /items/ 节点,而是尝试使用 $asArray()。然后,您可以遍历它的选项,并在您想要更新选项时单独调用它们 $save() 。这样,您不会在每次更改一个选项时保存整个集合,这几乎就是 $bindTo() 的工作原理。如果您有很多项目/选项,那根本无法扩展。
  • 请看我上面的编辑...
  • 我不太确定你从哪里得到 fbutil.syncArray... 这不是你应该使用的 AngularFire API。相反,使用 AngularFire 的 $asArray() 方法,您可以从任何 $firebase 对象调用该方法。另外,您第二次看到什么错误?一个最小化的 fiddle 或 codepen 将使这对我来说更容易,并且可以让我真正为你提供一个固定/工作的例子。
  • 哎呀,我没有解释。我正在使用 angularfire 种子应用程序 (see on github) 中的包装函数。我会试着想出一个笨拙的例子

标签: angularjs angularjs-ng-repeat firebase angularfire


【解决方案1】:

在 Firebase 中存储数据时,使用正确的数据结构非常重要。您选择的数据结构不适用于 Firebase。您需要一个诊断列表,每个诊断列表都有一个测试列表。但是,像您一样简单地嵌套它们会迫使 Firebase 将它们强制转换为伪数组。您应该通过push() method 添加每个诊断/测试来明确它是一个列表。请阅读our new docs on saving lists of data 了解如何选择一个好的 Firebase 数据结构。您正在该部分顶部执行大型“反模式”,我们建议您避免这样做。

使用您提供的 Plunkr,我继续制作了 a new demo Firebase(因为我无法查看/编辑您的个人 Firebase)。我将数据存储在更好的 Firebase 数据结构中。然后,我只需对您的 Plunkr 进行一些编辑即可制作 this working example。代码应该是不言自明的。在您看来,循环测试当前诊断,然后将诊断传递给您的saveChange() 方法:

<div ng-repeat="test in diagnosis.tests" class="list-group-item">
  <h4>{{test.title}} - {{test.outcome}}</h4> 

  <input type="checkbox" ng-model="test.outcome" ng-true-value="positive" ng-false-value="negative" ng-change="saveChange(diagnosis)" /> Positive

  <input type="checkbox" ng-model="test.outcome" ng-true-value="negative" ng-false-value="positive" ng-change="saveChange(diagnosis)" /> Negative
</div>

在您的控制器中,只需在 $scope.diagnoses 上调用 $save()

$scope.saveChange = function(diagnosis) {
  $scope.diagnoses.$save(diagnosis);
}

就是这样!

【讨论】:

  • Firebase 和 Plunkr 链接现在似乎已失效。有什么办法可以在答案中添加更多相关代码?
猜你喜欢
  • 1970-01-01
  • 2017-12-24
  • 2014-08-24
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 1970-01-01
  • 2019-03-16
  • 1970-01-01
相关资源
最近更新 更多