简体   繁体   中英

How to handle large URL parameters in Angular

In my hotel booking application which consists of multiple stages like Hotel Search -> Select Hotel -> Select Room -> Payment and each stage having different page. All the stages expect many inputs from previous stage (around 5-8 in some cases), like session-id, check-in, check-out and so on. I'm using Query Params for in-app navigation because when user refresh the page it shouldn't break.

The problem I'm facing is, too many fields makes the URL ugly and also nginx throws error at some stage because of large URL. I have tried storing this data in service but it doesn't help because when refreshing the page the data is lost & storing in localStorage doesn't looks fine. So, what is right or best approach I can take here to avoid this problems?

I would introduce an entity to your domain called something like BookingDraft , where you are building a booking but it is not a fully featured booking yet.

This entity should have its own unique ID, which will go in the URL. It should also have the user ID on it if you are going to persist this draft entity to a database.

export interface BookingDraft {
  // Unique identifier for this draft, such as a GUID. Can be persisted to a database, API, or to localStorage. This should go in the URL.
  id:string;
  userId:string;
  hotelId?:string;
  roomId?:string;
  checkIn?:Date;
  checkOut?:Date;
  sessionId?:string;
}

Then, your routes would have the booking ID in it, followed by a segment for the step.

/create-booking/{bookingDraftId}/select-hotel
/create-booking/{bookingDraftId}/select-room
/create-booking/{bookingDraftId}/payment

You can add a guard or some sort of validation logic to each segment's route to make sure the draft already has a hotelId before the user tries to select a room:

const routes: Routes = [
  {
    path: 'create-booking/:bookingDraftId',
    children: [
      {
        path: 'select-hotel',
        component: SelectHotelPageComponent
      },
      {
        path: 'select-room',
        component: SelectRoomPageComponent,
        canActivate: [HotelSelectedGuard]
      },
    ]
  }
]

export class HotelSelectedGuard implements CanActivate {
  constructor(private bookingDraftService: BookingDraftService, private router: Router) {}

  public canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean|UrlTree> {
    const draftId = next.paramMap.get('bookingDraftId');

    return this.bookingDraftService
      .getDraft(draftId)
      .pipe(map(draft => {
        if(!!draft.hotelId) {
          return true;
        }

        return this.router.createUrlTree(['create-booking',draftId,'select-hotel'], {
          queryParams: {
            message: 'Please select a hotel before selecting a room'
          }
        })
      }))
  }
}

Create a BookingDraftService to save and retrieve the booking draft(s) to and from localStorage or some API.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM