【问题标题】:Angular 5: How do I sort Observable alphabetically?Angular 5:如何按字母顺序对 Observable 进行排序?
【发布时间】:2018-04-12 12:26:32
【问题描述】:

我有一个无法解决的问题:我想按字母顺序对 Observable 中的数据进行排序(我认为至少是这样)。

代码的基本作用是从 Firestore 获取数据,并在事件标题栏中显示它从数据库中获取的 startHour 和 startMinute 变量。这很好用。但是,它不能正确地对“标题”进行排序。它不是按字母顺序对它们进行排序(例如,较早的时间首先是 07:20,然后是 10:50,然后是 13:05),而是根据数据库中显示的文档 ID 对其进行排序。所以基本上它可以变成07:20,然后是13:05,然后是10:50,这不是我想要的。

calendar.component.ts:

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Subject } from 'rxjs/Subject';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Observable } from 'rxjs/Observable';

import { MatDialog, MatDialogRef } from '@angular/material';
import { startOfDay, isSameDay, isSameMonth } from 'date-fns';

import { CalendarEvent, CalendarEventAction, CalendarEventTimesChangedEvent, CalendarMonthViewDay } from 'angular-calendar';

import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component';
import { fuseAnimations } from '@fuse/animations';

import { FuseCalendarEventFormDialogComponent } from './event-form/event-form.component';
import { CalendarEventModel } from './event.model';

import 'rxjs/add/operator/map';

export interface Ride { allDay: boolean; color: Object; /*primary: string; secondary: string;*/ end: Date; meta: Object; location: string; notes: string; start: Date; title: string; draggable: boolean; }
export interface RideId extends Ride { id: string }

@Component({
    selector     : 'fuse-calendar',
    templateUrl  : './calendar.component.html',
    styleUrls    : ['./calendar.component.scss'],
    encapsulation: ViewEncapsulation.None,
    animations   : fuseAnimations
})
export class FuseCalendarComponent implements OnInit
{   
    view: string;
    viewDate: Date;
    events: CalendarEvent[];
    locale: string = 'nl';
    public actions: CalendarEventAction[];
    activeDayIsOpen: boolean;
    refresh: Subject<any> = new Subject();
    dialogRef: any;
    confirmDialogRef: MatDialogRef<FuseConfirmDialogComponent>;
    selectedDay: any;
    rides: Observable<RideId[]>;
    ride: Observable<Ride>;

    private ridesCollection: AngularFirestoreCollection<Ride>;
    private ridesDocument: AngularFirestoreDocument<Ride>;



    vehicles = [
        {value: 'vehicle-0', viewValue: 'Alle'},
        {value: 'vehicle-1', viewValue: 'Buurtmobiel Beuningen/Weurt'},
        {value: 'vehicle-2', viewValue: 'Buurtmobiel Ewijk/Winssen'}
    ];

    constructor(
        public dialog: MatDialog,
        private readonly db: AngularFirestore,
    )
    {
        this.view = 'month';
        this.viewDate = new Date();
        this.activeDayIsOpen = true;
        this.selectedDay = {date: startOfDay(new Date())};



        this.actions = [
            {
                label  : '<i class="material-icons s-16">edit</i>',
                onClick: ({event}: { event: CalendarEvent }): void => {
                    this.editEvent('edit', event);
                }
            },
            {
                label  : '<i class="material-icons s-16">delete</i>',
                onClick: ({event}: { event: CalendarEvent }): void => {
                    this.deleteEvent(event);
                }
            }
        ];

        /**
         * Get events from service/server
         */
         this.ridesCollection = db.collection<Ride>('rides');

         this.rides = this.ridesCollection.snapshotChanges().map(actions => {
            return actions.map(a => {
            let data = a.payload.doc.data() as Ride;
                data.draggable = true;
            const id = a.payload.doc.id;
            return { id, ...data };
      });       
    });

//        this.setEvents();
    }

    ngOnInit()
    {
        /**
         * Watch re-render-refresh for updating db
         */
//        this.refresh.subscribe(updateDB => {
//            // console.warn('REFRESH');
//            if ( updateDB )
//            {
//                // console.warn('UPDATE DB');
//                this.calendarService.updateEvents(this.events);
//            }
//        });

//        this.calendarService.onEventsUpdated.subscribe(events => {
//            this.setEvents();
//            this.refresh.next();
//        });

//        this.ridesDocument = this.db.doc('rides/id');
//        this.ride = this.ridesDocument.valueChanges();
    }

    /**
     * Before View Renderer
     * @param {any} header
     * @param {any} body
     */
    beforeMonthViewRender({header, body})
    {
        // console.info('beforeMonthViewRender');
        /**
         * Get the selected day
         */
        const _selectedDay = body.find((_day) => {
            return _day.date.getTime() === this.selectedDay.date.getTime();
        });

        if ( _selectedDay )
        {
            /**
             * Set selectedday style
             * @type {string}
             */
            _selectedDay.cssClass = 'mat-elevation-z3';
        }

    }

    /**
     * Day clicked
     * @param {MonthViewDay} day
     */
    dayClicked(day: CalendarMonthViewDay): void
    {
        const date: Date = day.date;
        const events: CalendarEvent[] = day.events;

        if ( isSameMonth(date, this.viewDate) )
        {
            if ( (isSameDay(this.viewDate, date) && this.activeDayIsOpen === true) || events.length === 0 )
            {
                this.activeDayIsOpen = false;
            }
            else
            {
                //Titlebar(s) that appear(s) when a day has been selected

                this.activeDayIsOpen = true;
                this.viewDate = date;
            }
        }
        this.selectedDay = day;
        this.refresh.next();
    }

    /**
     * Event times changed
     * Event dropped or resized
     * @param {CalendarEvent} event
     * @param {Date} newStart
     * @param {Date} newEnd
     */
    eventTimesChanged({event, newStart, newEnd}: CalendarEventTimesChangedEvent): void
    {
        event.start = newStart;
        event.end = newEnd;

//        console.warn('Dropped or resized', event);

        this.ridesDocument = this.db.doc('rides/' + event.id);
        console.log(event.start);
        console.log(newStart);
        this.ridesDocument.update(event);
        this.refresh.next(true);
    }

    /**
     * Delete Event
     * @param event
     */
    deleteEvent(ride)
    {
        this.confirmDialogRef = this.dialog.open(FuseConfirmDialogComponent, {
            disableClose: false
        });

        this.confirmDialogRef.componentInstance.confirmMessage = 'Are you sure you want to delete?';

        this.confirmDialogRef.afterClosed().subscribe(result => {
            if ( result )
            {
//                const eventIndex = this.events.indexOf(event);
//                this.events.splice(eventIndex, 1);
//                this.refresh.next(true);

            }
            this.confirmDialogRef = null;
        });

    }

    /**
     * Edit Event
     * @param {string} action
     * @param {CalendarEvent} event
     */
    editEvent(action: string, event: CalendarEvent)
    {
//        const eventIndex = this.events.indexOf(event);

        this.dialogRef = this.dialog.open(FuseCalendarEventFormDialogComponent, {
            panelClass: 'event-form-dialog',
            data      : {
                event : event,
                action: action
            }
        });

        this.dialogRef.afterClosed()
            .subscribe(response => {
                if ( !response )
                {
                    return;
                }
                const actionType: string = response[0];
                const formData: FormGroup = response[1];
                switch ( actionType )
                {
                    /**
                     * Save
                     */
                    case 'save':
                        let saveData: any;
//                        this.events[eventIndex] = Object.assign(this.events[eventIndex], formData.getRawValue());
                        this.refresh.next(true);

                        saveData = formData.getRawValue();
//                        saveData.start.setHours(saveData.startHour);
//                        saveData.start.setMinutes(saveData.startMinute);

                        this.ridesDocument = this.db.doc('rides/' + event.id);
                        saveData.start.setHours(saveData.startHour, saveData.startMinute);
                        saveData.end.setHours(saveData.endHour, saveData.endMinute);
                        this.ridesDocument.update(saveData);

                        break;
                    /**
                     * Delete
                     */
                    case 'delete':

//                        this.deleteEvent(event);
                        this.ridesDocument = this.db.doc('rides/' + event.id);
                        this.ridesDocument.delete();

                        break;
                }
            });
    }

    /**
     * Add Event
     */
    addEvent(): void
    {
        this.dialogRef = this.dialog.open(FuseCalendarEventFormDialogComponent, {
            panelClass: 'event-form-dialog',
            data      : {
                action: 'new',
                date  : this.selectedDay.date
            }
        });
        this.dialogRef.afterClosed()
            .subscribe((response: FormGroup) => {
                if ( !response )
                {
                    return;
                }
                const newEvent = response.getRawValue();
//                newEvent.actions = this.actions;
//                this.events.push(newEvent);
                this.refresh.next(true);
                newEvent.start.setHours(newEvent.startHour, newEvent.startMinute);
                newEvent.end.setHours(newEvent.endHour, newEvent.endMinute);
                this.ridesCollection.add(newEvent);
            });
    }
}

我尝试过使用管道以及 .sort() 和 orderBy,但它什么都不喜欢。也许我做错了,我不能说,所以我很想在这个问题上得到一些帮助。

我使用 Fuse2 和 Angular 5。数据库是 Angularfire2 Firestore。

任何帮助将不胜感激!

编辑:我不确定这是否有任何帮助,但我可以将 .sort() 放在这里:

this.rides = this.ridesCollection.snapshotChanges().map(actions => {
            return actions.map(a => {
            let data = a.payload.doc.data() as Ride;
                data.draggable = true;
            const id = a.payload.doc.id;
            return { id, ...data };
      }).sort(); // Can add .sort() here without an error, but nothing happens
    });

但正如评论所说,它什么都不做,每当我尝试在 () 之间放置一个参数时,我都会收到一条错误消息......

【问题讨论】:

  • 尝试使用 loadash 进行排序。访问stackoverflow.com/questions/45813478/…
  • @Krunal 如果 lodash 可以排序,那么 vanillaJS 也可以。他说他试过了,问题不在于用什么来排序,而在于如何排序。
  • trichetriche@他正在使用管道,所以我建议使用 lodash 并提供例如链接,这样可能会解决问题。
  • 我曾经尝试使用管道来订购东西,但这也没有用。我一定是真的出了什么问题。

标签: javascript firebase rxjs google-cloud-firestore angularfire2


【解决方案1】:

Firebase 有一个内置功能,可以根据您想要的标准和方向进行排序。

对于firestore,你可以look here,对于实时数据库,你可以look here

【讨论】:

  • 谢谢,但我已经看过了,但由于某种原因它没有用。也许我做错了什么,但我无法弄清楚。因为我只是一个初学者,所以我缺乏这方面的知识。
  • db.collection&lt;Ride&gt;('rides').orderBy('titles', 'asc').
  • 谢谢,这也是我尝试过的,但无论我尝试什么,我每次都会收到此错误消息:TS2339: Property 'orderBy' does not exist on type 'AngularFirestoreCollection或与 .sort() 类似的东西
  • 再次阅读文档,您需要在文档的引用上使用此属性。这一切都得到了解释,即使在您使用的 firebase 库中:github.com/angular/angularfire2/blob/master/docs/firestore/…
  • db.collection&lt;Ride&gt;('rides', ref =&gt; ref.orderBy('titles', 'asc'))
猜你喜欢
  • 1970-01-01
  • 2011-08-29
  • 2010-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-22
  • 1970-01-01
相关资源
最近更新 更多