AngularJS - 在服务内部对数组进行排序,在控制器/视图中保留绑定

AngularJS - Sort array inside service, retain binding in controller/view

本文关键字:控制器 视图 绑定 保留 排序 服务 内部 数组 AngularJS      更新时间:2023-09-26

我正在寻找一种在 Angular 服务中对数组进行排序的方法,并且仍然在控制器中保留正确的绑定。

如果我跳过排序,绑定效果很好,但数组没有按照我的需要排序。

每当我使用 Lodash 的 _.sortBy 或 angular 的 $filter('orderBy') 服务执行排序时,都会发生以下两种情况之一:

  1. 服务中的数组已正确排序,但由于控制器不再引用同一数组,因此与控制器的绑定被切断。

  2. 如果我尝试使用 Lodash 的 _.cloneDeep 或 angular 的 angular.copy 来解决此问题,浏览器会因循环引用而冻结(?

服务.js

    angular.module('exampleapp')
.factory('ClientFeedService', function($filter, $firebase, FIREBASE_URL, FeedItemService) {
  return function(clientId) {
    var ClientFeedService = this;
    var ref = new Firebase(FIREBASE_URL + 'feeds/clients/' + clientId);
    var initialDataLoaded = false;
    ClientFeedService.feedArray = [];
    ClientFeedService.sortItems = function() {
      // Sorting logic here
    };

    /**
     * Bind to the initial payload from Firebase
     */
    ref.once('value', function() {
      // Sort items after initial payload
      ClientFeedService.sortItems();
      initialDataLoaded = true;
    });

    /**
     * Bind to new items being added to Firebase
     */
    ref.on('child_added', function(feedItemSnap) {
      console.log('child_added');
      ClientFeedService.feedArray.unshift(FeedItemService.find(feedItemSnap.name(), feedItemSnap.val()));
      // Sort after new item if initial payload loaded
      if (initialDataLoaded) {
        ClientFeedService.sortItems();
      }
    });
    ClientFeedService.getFeedItems = function() {
      return ClientFeedService.feedArray;
    };
    return ClientFeedService;
  };
});

控制器.js

    app.controller('ClientsFeedCtrl', function($scope, $stateParams, ClientFeedService) {
  var clientId = $stateParams.clientId;
  $scope.clientFeed = new ClientFeedService(clientId).getFeedItems();
});

有几种方法可以解决这个问题。 首先,让我们看看发生了什么。

您正在将初始数组分配给 $scope.cliendFeed 。 在此之后,随着数据的添加,将生成一个新的数组并将其存储在服务中,但您仍然可以引用原始数组。 因此,最终,您要做的是找到一种方法来使$scope.clientFeed与您的服务保持同步。

最简单的解决方案可能是使用 getter 方法,而不是在作用域中存储对数组的引用。

为此,您必须添加如下内容:

var service = new ClientFeedService(clientId);
$scope.getClientFeed = function () {
  return service.getFeedItems();
};

并确保您的ng-repeat调用了此函数:

<li ng-repeat="item in getClientFeed()">...</li>

希望对您有所帮助!

  1. 您可以将从 API 返回的新数据推送到控制器中的同一数组,然后应用$filter
  2. 这是示例

    function getData(){
       $scope.array.push(returnData);
       sortArrayList($scope.orderByField, $scope.reverseSort);
    }
    function sortArrayList(orderByField, reverseSort){
       $scope.array = $filter('orderBy')($scope.array, orderByField, reverseSort);
    }