使用嵌套的ng-repeat来迭代Angularfire 0.8中的firebase对象

时间:2014-08-21 14:44:03

标签: angularjs angularjs-ng-repeat firebase angularfire

我的目标:

我有一个需要迭代的列表。此列表中的每个项目都有一个自己的列表(嵌套)。对于这些嵌套列表项中的每一个,我需要有一组两个复选框,供用户指定他们的选择。我需要将这些复选框选项同步回到应与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在评论中的帖子:

  

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

/////////修改

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

这是我想要做的事情的一部分:

Plunker example

我有一个'saveChange()'函数,我不知道如何实现

1 个答案:

答案 0 :(得分:4)

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

使用您提供的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>

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

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

那就是它!