0

Currently I am using this snippet to set 6 days and some time slots for each day in my firebase database.

fb.$set({
  monday: {
    name: 'Monday',
    slots: {
      900: {
        time: '9:00am',
        booked: false
      },
      0110: {
        time: '11:00am',
        booked: false
      },
      100: {
        time: '1:00pm',
        booked: false
      },
      300: {
        time: '3:00pm',
        booked: false
      },
      500: {
        time: '5:00pm',
        booked: false
      },
      700: {
        time: '7:00pm',
        booked: false
      }
      }
  },
  tuesday: {
    name: 'Tuesday',
    slots: {
      900: {
        time: '9:00am',
        booked: false
      },
      0110: {
        time: '11:00am',
        booked: false
      },
      100: {
        time: '1:00pm',
        booked: false
      },
      300: {
        time: '3:00pm',
        booked: false
      },
      500: {
        time: '5:00pm',
        booked: false
      },
      700: {
        time: '7:00pm',
        booked: false
      }
      }
  },
  wednesday: {
    name: 'Wednesday',
    slots: {
      900: {
        time: '9:00am',
        booked: false
      },
      0110: {
        time: '11:00am',
        booked: false
      },
      100: {
        time: '1:00pm',
        booked: false
      },
      300: {
        time: '3:00pm',
        booked: false
      },
      500: {
        time: '5:00pm',
        booked: false
      },
      700: {
        time: '7:00pm',
        booked: false
      }
      }
  },
  thursday: {
    name: 'Thursday',
    slots: {
      900: {
        time: '9:00am',
        booked: false
      },
      0110: {
        time: '11:00am',
        booked: false
      },
      100: {
        time: '1:00pm',
        booked: false
      },
      300: {
        time: '3:00pm',
        booked: false
      },
      500: {
        time: '5:00pm',
        booked: false
      },
      700: {
        time: '7:00pm',
        booked: false
      }
      }
  },
  friday: {
    name: 'Friday',
    slots: {
      900: {
        time: '9:00am',
        booked: false
      },
      0110: {
        time: '11:00am',
        booked: false
      },
      100: {
        time: '1:00pm',
        booked: false
      },
      300: {
        time: '3:00pm',
        booked: false
      },
      500: {
        time: '5:00pm',
        booked: false
      },
      700: {
        time: '7:00pm',
        booked: false
      }
      }
  },
  saturday: {
    name: 'Saturday',
    slots: {
      900: {
        time: '9:00am',
        booked: false
      },
      0110: {
        time: '11:00am',
        booked: false
      },
      100: {
        time: '1:00pm',
        booked: false
      },
      300: {
        time: '3:00pm',
        booked: false
      },
      500: {
        time: '5:00pm',
        booked: false
      },
      700: {
        time: '7:00pm',
        booked: false
      }
      }
  }
});

Note the order. Why then is it stored alphabetically ?

database order

This then becomes a problem when I return this data and iterate over it on the page as the days aren't in the order you would expect but return alphabetically.

Is there a way I can have some degree of control over this?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Smiter
  • 1,069
  • 1
  • 14
  • 33
  • 1
    why don't you make them sort on ui using `orderBy` filter while displaying it.. – Pankaj Parkar Oct 30 '15 at 14:05
  • 1
    https://www.firebase.com/docs/rest/guide/retrieving-data.html#section-rest-filtering Check that warning!! Check this answer, http://stackoverflow.com/questions/31808990/firebase-returning-keys-of-child-node-in-different-orders-on-different-devices-a – Sudhansu Choudhary Oct 30 '15 at 14:13
  • yep v helpful! Thank you – Smiter Oct 30 '15 at 14:21
  • Is there any reason you are not using a timestamp format YYYYmmddHHMMSS? If you do that, you can orderBy timestamp and it will be correct every time. Just add it as a child of each node. You can always read it in and convert to day, date, time, whatever you need. You could also keep a string of the time or day part if you needed it. – Jay Oct 30 '15 at 20:55

4 Answers4

0

You'll need to pass a function to the orderBy filter that will perform your custom sorting.

var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
    $scope.name = 'Superhero';
    
    $scope.days = [
        { name: 'Monday' },
        { name: 'Tuesday' },
        { name: 'Wednesday' },
        { name: 'Thursday' },
        { name: 'Friday' },
        { name: 'Saturday' },
        { name: 'Sunday' }
    ]
    
    $scope.sortByWeekday = function (day) {
        var weekdays = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
        return weekdays.indexOf(day.name.toLowerCase());
    }
}
<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
  </head>
  <body ng-app="myApp">
    <div ng-controller="MyCtrl">
      <div ng-repeat="day in days | orderBy:sortByWeekday">{{day.name}}</div>
    </div>
  </body
</html>
phuzi
  • 12,078
  • 3
  • 26
  • 50
  • Sorry Phuzi I like this answer but it wouldn't stick. When I reset the application the days appeared in the correct order and them instantly get replaced in the order coming from FB :( – Smiter Oct 30 '15 at 15:32
  • @Smiter Weird, must be something else going on that's updating the view. – phuzi Oct 30 '15 at 15:36
0

I think you're looking for $priority. Ordering data in firebase is done first by $priority and second by key. There's a bunch of documentation on how sorting works in Firebase that would be good to read up on. I'd use $priority if you're trying to specifically store data (and get it back) in a predetermined order.

sonicblis
  • 2,926
  • 7
  • 30
  • 48
0

The Firebase database stores JSON data. The keys in a JSON object are inherently unordered. In most cases the Firebase SDKs will return the keys in alphabetical order by default.

In general Firebase recommends against using arrays, but if this case is exception to that general recommendation you could do:

set({
  1: {
    name: 'Monday',
    slots: {
      900: { time: '9:00am', booked: false },
      1100: { time: '11:00am', booked: false },
      1300: { time: '1:00pm', booked: false },
      1500: { time: '3:00pm', booked: false },
      1700: { time: '5:00pm', booked: false },
      1900: { time: '7:00pm', booked: false }
    }
  },
  2: {
    name: 'Tuesday',
    slots: {
      900: { time: '9:00am', booked: false },
      1100: { time: '11:00am', booked: false },
      1300: { time: '1:00pm', booked: false },
      1500: { time: '3:00pm', booked: false },
      1700: { time: '5:00pm', booked: false },
      1900: { time: '7:00pm', booked: false }
    }
  },
  3: {
    name: 'Wednesday',
    slots: {
      ...

In the above snippet I also changed the keys of the slots. By using 24-hour notation for the time, they'll be automatically ordered the way you want them to be.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks Frank, this is what I have used ! Not extremely scalable but will cross that bridge when I get there :) – Smiter Oct 30 '15 at 15:31
0

I posted a comment above, and without knowing the scope of the project it's hard to know the exact direction to recommend. However, using day names as a key and times stored as strings will probably not work well long term.

The simple answer is to store the date and time of the time slot/event as a timestamp in a format like YYYYmmddHHMMSS, as a child node of the slot.

So for example

training_classes
   training_id_1234
     timestamp: 20151031130000
     trainer: trainer_id1234
     client: client_id1234
     comment: "Algebra 1"
   training_id_3445
     timestamp: 20151031150000
     trainer: trainer_id1234
     client: client_id1234
     comment: "Algebra 2"

With this structure, you can easily query for all classes on Saturday Oct 31st. In the above case there are two, one at 1pm and one at 3pm.

The other times have no data so those are available to be booked (eliminating the need to store booked:false) in firebase.

You can also sort them easily as the time stamp is always in chronological order - the order its stored in Firebase doesn't matter.

Also, it makes changing the training event super easy. Just update the timestamp and whammo, it's rescheduled.

Jay
  • 34,438
  • 18
  • 52
  • 81