Is it possible to use .sort (compare) and .reverse array in angularfire?

Update: The problem I encountered consists of three things:

  • Adding a title to the array when the priority of $ (set to date) changes. This means that I can group tasks by week and day in ng-repeat.
  • Assigning this list when checking a task. Checked tasks should be below.
  • When creating new tasks, I need to add them to the top of the list, not the bottom.

Here is the plnkr of the whole code: http://plnkr.co/edit/A8lDKbNvhcSzbWVrysVm

I use the priorityChanged function to add a header based on a date comparison for the task: // controller var last = null; $ scope.priorityChanged = function (priority) {var current = moment (priority) .startOf ('day'); var changed = last === null ||! Last.isSame (current); last = current; Refund changed };

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

and move the task to the bottom of the list when the task is completed. I use the .sort function when populating the task list:

 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; }; 

It seems that these approaches will not work together. Is there a way to combine them so that when the list is re-sorted, ng-repeat will complete the tasks again and add the necessary headers? Is this the perfect solution? Can the title be separate?

Update. I moved the ng-init function directly to h3 to try to run it, but in this case does not display the header.

Update2: It seems that the title appears if at least two of the priority dates $ are unique, but I still have the problem of deleting or moving the linked list item that deletes the connected title.

0
source share
2 answers

USE OF DIRECTIVES

You can create a directive to simplify actions by nesting the contents of your client. demo

 app.directive('repeatByWeek', function($parse, $window) { return { // must be an element called <repeat-by-week /> restrict: 'E', // replace the element with template 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 template:

 <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 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> 

OTHER IDEAS

Most likely, you just need to push the changes from ng-init. I don't think this is re-execution when items are moved / resorted to.

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

Since your list can be resorted to several times, you can also get quite significant speedups using the track .

 <li ng-repeat="task in list track by task.$id"> 

If this does not solve the problem, maybe it's time to think about writing your own directive (it's funnier than they sound) and maybe consider removing AngularFire and going straight to the source.

You really need a more deeply nested data structure here, you can iterate at several levels, and you may need to structure it yourself either on the client or on the server, now that you have an idea of ​​how you want them to be organized (essentially the functionality of the group per week).

+2
source

you can use unshift "javascript function

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

Result

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

All Articles