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
Both urls render a list of posts. Lets set up the controller and the page_to_page_mapping.js the same way.
=== "posts_controller.rb" !!! info "Same template different action" 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.
```ruby
# app/controllers/posts_controller.rb
def index
@posts = Post.all
end
def new
@posts = Post.all
render :index
end
```=== "page_to_page_mapping.js" !!! info Similarly, we tie the componentIdentifier to the same page component.
Add a link to /posts/new
/posts/newImagine 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.props" ```ruby # app/views/posts/index.json.props
=== "posts/index.js" ```js import { useContent } from '@thoughtbot/superglue'
The modal
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.
=== "posts/index.json.props" !!! info For simplicity, we'll use a "Hello World" as the modal contents ```diff # app/views/posts/index.json
=== "index.js" ```diff + import Modal from './Modal'
=== "Modal.js"
Too many modals
Unfortunately, now BOTH routes have modals! Lets fix that by adding a conditional render.
=== "index.json.props" ```diff # app/views/posts/index.json.props
=== "posts_controller.rb" ```diff # app/controllers/posts_controller.rb
=== "Modal.js" ```diff import Modal from './Modal'
Finish!
Awesome! We have modals! Unfortunately, clicking <a href={newPostPath}>New Post</a> will cause a new page load. We can remove 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.jsOptimization
With the above, a click on New Post while on /posts will
Fetch
/posts/newwithformat=jsonSave 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.jsonRecall 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.
With that change, the sequence becomes:
Copy the state in
/poststo/posts/newin the store.Fetch
/posts/new?props_at=data.createPostModalGraft the result to the store at
/posts/newSwap the page components
Change the url
Last updated
Was this helpful?