【问题标题】:Angular ngRepeat not preserving order of Firebase priority items?Angular ngRepeat 不保留 Firebase 优先项目的顺序?
【发布时间】:2015-01-04 20:50:18
【问题描述】:

这里是 Angular 和 Firebase 的新手,但注意到查询和呈现有序数据的奇怪行为,但在其他任何地方都没有解决......

我正在将数据推送到 Firebase 并使用递减的负值设置优先级,以便最新数据位于列表顶部。

当使用child_added 事件检索引用时,我可以确认数据以正确的顺序到达;但是,当与 ngRepeat 一起使用时,数据会以某种方式反转(最新数据显示在 ngRepeat 列表的底部)。

如果我使用.append() 之类的东西,则数据是正确排序的。但宁愿使用 ngRepeat 以“Angular”方式进行。

// example html binding
// ====================================
<ul>
    <li ng-repeat="(itemID, item) in list">{{itemID}}</li>
</ul>


// example controller code
// ====================================
var laApp = angular.module('laApp', ['firebase']);

laApp.controller('laAppCtrl', function ($scope, $timeout){
    var ref = new Firebase('https://ngrepeatbug.firebaseio.com');

    $scope.pushPriority = function(){
        var uid = new Date().getTime();
        var priority = 0 - uid;
        // set with -priority so newest data on top
        ref.push().setWithPriority(uid, priority);
    }

    $scope.list = {};
    ref.orderByPriority().on('child_added', function(snap){
        $timeout(function(){
            var snapID = snap.key();
            var snapVal = snap.val();

            //repeat method
            $scope.list[snapID] = snap.val();

            //append method
            $('ul.append').append("<li>" + snapVal + "</li>")
        })
    })
});

比较 ngRepeat 和 append 方法: http://codepen.io/juddam/pen/dIiLz

我读过其他解决方案,它们要么将 $scope.list 对象转换为数组,然后与 $filter 一起使用,要么在客户端反转顺序,但这违背了按优先级存储数据的整个目的,并有一个简单的方法查询和呈现有序数据。

Know orderByPriority 是 firebase v2.0 的新手,所以想知道是 bug 还是我遗漏了一些明显的东西?

【问题讨论】:

  • javascript 中的对象没有设置键顺序,因此如果不将它们放入数组并对其进行排序,就无法保证哪个键会在另一个键之前显示。
  • 谢谢 Zack - 我知道,但由于显示顺序始终处于相反顺序,因此可能会遗漏其他内容。

标签: angularjs angularjs-ng-repeat firebase


【解决方案1】:

您正在将孩子添加到对象中:

 $scope.list[snapID] = snap.val();

尽管这看起来像是在添加到数组中,但实际上是在添加到常规对象。正如@ZackArgyle 在他的评论中所说:对象中的键没有保证顺序。

如果你想保持项目的顺序,你应该把它们压入一个数组中。

 $scope.list.push(snap.val());

这会为它们添加数字索引,这将保持它们的顺序。

如果您想同时维护项目的顺序它们的键,则必须在数组中管理它们。

 $scope.list.push({ $id: snap.key(), value: snap.val() });

最后一种方法是 AngularFire 在调用 $asArray() 时所做的极其简化的版本。

【讨论】:

  • 另外,该方法忽略了 prevChild。从服务器到达的项目也没有保证的顺序。所以在使用 child_add 时,观察 prevChild 以确定它们在数组中的位置也很重要。 AngularFire 绑定的另一个特性。
  • @Kato 好点。在这种情况下,尽管使用orderByPriority()child_added 进行初始视图加载。所以如果以后收到child_added事件就得观察prevChild。
  • 谢谢@Frank - 会支持但没有足够的信誉:) 这是一个更大的服务的一部分,它将整理去规范的 firebase 数据。我在其他地方使用 AngularFire,但 read $asArray() will download all data。由于我使用它来管理和渲染图像数据,因此担心浏览器过载。
猜你喜欢
  • 2023-03-20
  • 2018-09-04
  • 2018-05-02
  • 1970-01-01
  • 1970-01-01
  • 2020-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多