Modals
Modals are easy. Lets imagine a scenario where we have two urls:
/posts
/posts/new
When a user visits /posts/new
from /posts
, we want a modal to appear overlaying the existing list of posts. The overlay should work if a user chooses instead to directly visit /posts/new
.
The setup
Arriving at both urls results in a seeing list of posts. Lets set up the controller and the page_to_page_mapping.js
the same way.
posts_controller.rb
posts_controller.rb
?> Notice that we're rendering the index
for the new
action. While the content is the same, the componentIdentifier
is different as that has been setup to use the controller and action name.
page_to_page_mapping.rb
page_to_page_mapping.rb
?> Similarly, we tie the componentIdentifier
to the same page component.
Add a link to /posts/new
/posts/new
Imagine a list of posts, lets add a button somewhere on the index page to direct the user to /posts/new
. As seen previously, both /posts
and /posts/new
render the same thing.
posts/index.json
posts/index.json
posts/index.js
posts/index.js
?> Similarly, we tie the componentIdentifier
to the same page component.
The modal
Now the link appears and we're able to navigate to /posts/new
, but /posts/new
is missing a modal. Not surprising as both routes are rendering the same content.
Lets add a modal.
index.json
index.json
?> For simplicity, we'll use a "Hello World" as the modal contents
index.js
index.js
Modal.js
Modal.js
?> This is a simplified modal, in practice you'll use this with <Dialog>
or other modal library.
Too many modals
Unfortunately, now BOTH routes have modals! Lets fix that by adding a conditional render.
index.json
index.json
posts_controller.rb
posts_controller.rb
Modal.js
Modal.js
Finish!
Awesome! We have modals! Unfortunately, clicking <a href={newPostPath}>New Post</a>
will cause a new page load. We can move the page load by adding data-sg-visit
to the link. With data-sg-visit
, Superglue will navigate to the next page without reloading the page, just like Turbo.
posts/index.js
posts/index.js
Optimization
With the above, a click on New Post while on /posts
will
Fetch
/posts/new
withformat=json
Save the page to the store
Swap the page components
Change the url
Unfortunately, step 1 is still a full page load. Commonly, we just want to load the modal without loading the entire page.
Lets fix that!
index.json
index.json
Recall how digging for content works. We'll add a props_at
that digs for the modal on /posts/new
while skipping other content on that page.
posts/index.js
posts/index.js
Lastly add data-sg-placeholder
to the link.
With the placeholder, the sequence becomes:
Copy the state in
/posts
to/posts/new
in the store.Fetch
/posts/new?props_at=data.createPostModal
Graft the result to the store at
/posts/new
Swap the page components
Change the url
?> Normally, props_at
cannot be used with data-sg-visit
, that's because the state needs to exist for Superglue to know where to graft. With data-sg-placeholder
, we take an existing page and copy that over as a placeholder for what doesn't exist yet.
Last updated