select-your-own-seat

Expand History Expand History
Collapse History Collapse History

Progressively enhance Selection State

Our server already renders Seat elements with their selection state for full page reloads, but now that the <svg id="map"> element is annotated with data-turbolinks-permanent, the element will persist across Turbolinks-initiated visits.

Due to this persistence, our client is now responsible for managing some long-lived state. When a Seat is selected, a full-page visit modifies the HTML for the entire page, replacing the <body> element and its contents – except for the map.

This commit extends our client-side code to progressively enhance the application to manage changes in Seat selection state by managing the <use> element’s xlink:href attribute with Client-side logic.

In addition to checking setting the correct xlink:href at render-time, the server transmits additional information for each Seat (represented by data- attributes declared on its <use> element).

By reading data-seat-id values from the page’s Cart Summary, the Seats Stimulus controller modifies the <use> elements’ xlink:href attributes that represents the seats’ possible states.

The map of possible transitions is encoded as data-selected-icon and data-unselected-icon, which is made accessible through accessing element.dataset.selectedIcon and element.dataset.unselectedIcon.

When the xlink:href attribute is assigned to a new value, the browser will render the Seat that is referenced.

This state is managed by the seats#selectSeats function. That function must be run:

  1. When the page is loaded
  2. When a Seat is added to the Cart Summary
  3. When a Seat is removed from the Cart Summary

The first case can be covered by a direct invocation in the seats#connect life cycle hook. The second and third depend on how our users interact with the page’s <form> elements.

This commit passes the remote: true option to button_to and form_with helper method calls. This results in a data-remote="true" attribute on the resulting <form> element, which integrates with Rails’ Unobtrusive JavaScript.

During the life cycle of a UJS-initiated AJAX request, there are several events fired.

This commit extends the <form> elements interested in adding and removing Seats from the page’s cart summary by declaring data-action="ajax:complete->seats#selectSeats". This attribute routes the <form> element’s ajax:complete events to the seats#selectSeats action.