1

I have an angular 2 service apptService that returns Observable<Appointment[]> which I then order using the lodash sortBy function:

class Appointment {
    id: string;
    distance: number;
    appointmentDate: date;
}

getAppointments(sortOrder) {
   this.appointments = this
     .apptService
     .getAppointments()
     .map(v => _.sortBy(v, sortOrder));
}

I call getAppointments passing a sort function like so:

getAppointments((app: Appointment) => app.id);
getAppointments((app: Appointment) => app.distance);
getAppointments((app: Appointment) => app.appointmentDate);

The appointmentDate and id sorts are as expected, but when sorting by distance, the values are ordered alphanumerically ie: 12, 123, 15, 3

For now, I have bodged an unsightly solution using:

 getAppointments((app: Appointment) => {
   // this will only work for appointments up to 100000 miles away
   var s = "00000" + app.distance.toString();
   return s.substr(s.length - 5);
 });

but this breaks my pattern, so I am looking for a better solution, or hoping at least to understand why this is happening.

lodash was used for the sort because I liked the syntax and the ease of passing in the sorting arrow function, but am not attached to using it if there is a better solution.

And sorry but no plunker, I could not get lodash and typescript working together at all there.

5
  • It might be that your instance is still a string, i.e. not mapped to the right type from the http response json, try: getAppointments((app: Appointment) => parseInt(app.distance)); Commented Nov 8, 2016 at 20:35
  • Please share us a dump of one of your Appointment. I suspect that the distance is a string. You can try to parse the value by adding a + to the statement: getAppointments((app: Appointment) => +app.appointmentDate); Commented Nov 8, 2016 at 20:38
  • @meir typescript won't allow parseInt(app.distance) as parseInt is only for strings. I could parseInt(app.distance.toString()) but then I think I'd be back where I started. Commented Nov 8, 2016 at 20:51
  • Not sure, did you try it? You said that you get alphabetical instead of numeric sorting. My guess is that it is because though you think you hold numbers, you hold strings, I had similar cases and it took me a while to figure out. Give the parseInt(app.distance.toString()) a chance :-) Commented Nov 8, 2016 at 21:01
  • Thanks Polochon, Meir, you were both right - guess I need to investigate a bit more about what typescript does, and what it does not! Commented Nov 8, 2016 at 21:09

1 Answer 1

1

In my service I had this:

    let appointments = this
        .http
        .get("app/appointments.json")
        .map((r: Response) => r.json().appointments as Appointment[]);

Although each json object is cast as Appointment[], it appears this is perhaps just for the linters benefit?, and no actual conversion takes place. The properties get set as strings without regard to the class property types.

Making the following changes solved the problem.

let appointments = this
    .http
    .get("app/appointments.json")
    .map(this.mapAppointments);

private mapAppointments(response: Response): Appointment[] {
    return response.json().appointments.map((r) => {
        let g = new Appointment();
        g.id = r.id;
        g.appointmentDate = r.appointmentDate;
        g.distance = parseInt(r.distance);
        return g;
    });
}

Thanks to @Polochon and @Meir for leading me to this.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.