是不是可以在angularfire中进行.sort(比较)和.reverse数组?

时间:2014-09-25 20:56:03

标签: javascript angularjs firebase angularfire

更新:我遇到的问题是做三件事:

  1. 当$ priority(设置为创建日期)更改时,向数组添加标头。这样我就可以在ng-repeat中按周和日分组任务。
  2. 在检查任务时使用该列表。检查的任务应该放在最底层。
  3. 创建新任务时,我需要将它们添加到列表顶部而不是底部。
  4. 以下是所有代码的一部分:http://plnkr.co/edit/A8lDKbNvhcSzbWVrysVm

    我使用priorityChanged函数根据比较任务的日期添加标题:       //控制器       var last = null;       $ scope.priorityChanged = function(priority){         var current = moment(priority).startOf(' day');         var changed = last === null || !last.isSame(电流);         last = current;         回报改变了;       };

    //view
    <li ng-repeat="task in list track by task.$id">
      <h3 ng-show="priorityChanged(task.$priority)">{{getDayName(task.$priority)}}</h3>
    

    并在任务完成时将任务移动到列表底部我在填充任务列表时使用.sort函数:

    var populateTasks = function(start, end) {
        $scope.start = start;
        $scope.end = end;
        var ref = new Firebase('https://plnkr.firebaseio.com/tasks').startAt(start).endAt(end);
        var list = $firebase(ref).$asArray();
    
        list.sort(compare);
    
        list.$watch(function() {
          list.sort(compare);
        });
    
        function compare(a, b) {
          return a.completeTime - b.completeTime;
        }
    
        $scope.list = list;
    
      };
    

    似乎这些方法无法协同工作。有没有办法将它们组合起来,以便在重新排序列表时,ng-repeat将再次运行任务并添加必要的标题?这是理想的解决方案吗?标题可以分开吗?

    更新:我将ng-init功能直接移动到h3中以尝试再次运行,但在这种情况下它不会显示标题。

    Update2:如果至少有两个$ priority日期是唯一的,那么标题似乎会显示,但我仍然有删除或移动关联列表项删除连接标题的问题。

2 个答案:

答案 0 :(得分:2)

使用指令

您可以通过嵌套客户端内容来创建指令以简化操作。 demo

app.directive('repeatByWeek', function($parse, $window) {
  return {
    // must be an element called <repeat-by-week />
    restrict: 'E',
    // replace the element with template's contents
    replace: true,
    templateUrl: 'repeat.html',
    // create an isolate scope so we don't interfere with page
    scope: {
      // an attribute collection="nameOfScopeVariable" must exist
      'master': '=collection'
    },
    link: function(scope, el, attrs) {
      // get the global moment lib
      var moment = $window.moment;
      scope.weeks = [];
      updateList();

      // whenever the source collection changes, update our nested list
      scope.master.$watch(updateList);

      function updateList() {
         scope.weeks = sortItems(parseItems(scope.master));
      }

      function sortItems(sets) {
        var items = [];
        // get a list of weeks and sort them
        var weeks = sortDescending(Object.keys(sets));
         for(var i=0, wlen=weeks.length; i < wlen; i++) {
           var w = weeks[i];
           // get a list of days and sort them
           var days = sortDescending(Object.keys(sets[w]));
           var weekEntry = { 
             time: w, 
             days: []
           };
           items.push(weekEntry);
           // now iterate the days and add entries
           for(var j=0, dlen=days.length; j < dlen; j++) {
             var d = days[j];
             weekEntry.days.push({
               time: d,
               // here is the list of tasks from parseItems
               items: sets[w][d]
             });
           }
         }
         console.log('sortItems', items);
         return items;
      }

      // take the array and nest it in an object by week and then day
      function parseItems(master) {
        var sets = {};
        angular.forEach(master, function(item) {
           var week = moment(item.$priority).startOf('week').valueOf()
           var day = moment(item.$priority).startOf('day').valueOf();
           if( !sets.hasOwnProperty(week) ) {
             sets[week] = {};
           }
           if( !sets[week].hasOwnProperty(day) ) {
             sets[week][day] = [];

           }
           sets[week][day].push(item);
         });
         console.log('parseItems', sets);
         return sets;
      }

      function sortDescending(list) {
        return list.sort().reverse();
      }
    }
  }
});

repeat.html模板:

<ul>
    <!-- 
      it would actually be more elegant to put this content directly in index.html
      so that the view can render it, rather than needing a new directive for
      each variant on this layout; transclude should take care of this but I
      left it out for simplicity (let's slay one dragon at a time)
    -->
    <li ng-repeat="week in weeks">
    <h3>{{week.time | date:"MMMM dd'th'" }}</h3>
    <ul>
      <li ng-repeat="day in week.days">
        <h4>{{day.time | date:"MMMM dd'th'" }}</h4>
        <ul>
          <li ng-repeat="task in day.items">
            <input type="checkbox" ng-model="task.complete" ng-change="isCompleteTask(task)">
            <input ng-model="task.title" ng-change="updateTask(task)">
            <span ng-click="deleteTask(task)">x</span>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

其他想法

最有可能的是,您只需将更改后的ng-init移出。我不认为当元素移动/度假时会重新运行。

<li ng-repeat="task in list">
  <h3 ng-show="priorityChanged(task.$priority)">{{getDayName(task.$priority)}}</h3>
  <!-- ... -->
</li>

由于您的列表可能会多次使用,因此using track by

可能会显着提升速度。
<li ng-repeat="task in list track by task.$id">

如果这还没有解决问题,那么可能是时候考虑编写自己的指令(这些指令比听起来更有趣)并且可能考虑放弃AngularFire并直接进入源代码。

你真的想要一个更深层嵌套的数据结构,你可以在多个级别进行迭代,你可能需要在客户端或服务器上自己构建,现在你已经了解了你希望它们如何组织(基本上按周分组功能)。

答案 1 :(得分:0)

您可以使用“unshift”javascript功能

var fruits = ["1", "2", "3", "4"];
fruits.unshift("5","6");

结果

[ '5', '6', '1', '2', '3', '4' ]