Tutorial
Lets build a simple app to get familiar with superglue.
Hello world
1. Start with the usual
Add a route and a controller to an app that followed the installation steps.
!> The installation steps will include a layout application.json.props
that's implicitly used in this tutorial.
routes.rb
routes.rb
greet_controller.rb
greet_controller.rb
2. Add the views
Next lets add the following views. Here we're splitting the usual show.html.erb
into 3 parts:
app/views/greet/show.json.props
app/views/greet/show.js
app/views/greet/show.html.erb
show.json.props
show.json.props
If you've used Jbuidler, this should look familiar. Here, we're using props_template, a Jbuilder inspired templating DSL built for superglue.
?> Shape the page to how you would visually organize your components. Superglue encourages you to shape json
responses to include both data AND presentation.
show.js
show.js
The result of show.json.props
will be passed to your page component.
show.html.erb
show.html.erb
?> This file is usually generated by a scaffold and stays exactly the same regardless if its index.html.erb
, show.html.erb
, edit.html.erb
, etc.
This file renders and injects show.json.props
sets it globally as the initial state to be picked up by React and Redux.
3. Connect the dots
The json payload that gets rendered into show.html.erb
also contains information about the template it rendered from the componentIdentifier
.
?> If you do not knowing what the componentIdentifier
of a page is, you can go to the json
version of the page on your browser to see what gets rendered. In our case: http://localhost:3000/greet.json
We're going to use the componentIdentifier
to tie show.json.props
to show.js
so superglue knows which component to render with which response by modifying app/javascript/page_to_page_mapping.js
.
Example greet.json
The layout for show.json.props
is located at app/views/layouts/application.json.props
. It conforms to superglue's payload response, and uses the active_template_virtual_path
as the componentIdentifier
.
page_to_page_mapping.js
page_to_page_mapping.js
4. Finish
Run a rails server and go to http://localhost:3000/greet.
Productivity
That was quite an amount of steps to get to a Hello World. For simple functionality it's not immediately obvious where Superglue fits, but for medium complexity and beyond, Superglue shines where it can be clunky for tools like Turbo, Hotwire and friends.
Let's add some complexity to the previous sample.
Digging for content
But first! A quick dive into props_template. Click on the tabs to see what happens when @path
changes for the example below.
data
When @path = ['data']
. There's a 10 second sleep, and the output will be:
data.body
When @path = ['data', 'body']
. There's a 10 second sleep, and the output will be:
data.body.user
When @path = ['data', 'body', 'user']
, there is no wait, and the json
will be:
data.footer
When @path = ['data', 'year']
, there is no wait, and the json
will be:
5. Continuing where we last left off
Lets add a 5 second sleep to show.json.props
so ever user is waiting 5 seconds for every page load.
How should we improve the user experience?
show.json.props
show.json.props
6. Load the content later
What if we add a link on the page that would load the greeting async? Sounds like a good start, lets do that. We'll use defer: :manual
to tell props_template to skip over the block.
show.json.props
show.json.props
output
Adding defer: :manual
will replace the contents with an empty object.
show.js
show.js
We'll also have to handle the case when there is no greeting.
?> We'll improve on this approach. The defer
option can specify a fallback.
7. Add a link
Now when the user lands on the page, we're no longer waiting 5 seconds. Lets add a link that will dig for the missing content to replace "Waiting for greet".
show.json.props
show.json.props
Add url for the href
link with props_at
param. This is used on the application.json.props
layout that instructs props_template to dig.
show.js
show.js
Superglue embraces Unobtrusive Javascript. Add a data-sg-remote
to any link, and superglue will take care of making the fetch call.
show.js
alternative
show.js
alternativeThis version does the same thing. Every page component receives a remote
and visit
thunk.
8. Finish
And that's it. Now you have a button that will load content in async fashion, but how does it all work? Lets take a look at loadGreetPath
The shape of show.json.props
is exactly the same as what is stored in the redux store on pages["/greet"]
. With a single keypath on props_at
we grabbed the content at data.greet
from show.json.props
AND stored it on data.greet
on pages["/greet"]
.
Now that's productive!
9. Improvements
In practice, there's a far simpler solution: defer: :auto
, which would do all of the above without a button.
show.json.props
show.json.props
The only change needed would be to use the :auto
option with a placeholder. The response would tell Superglue to:
Save the page (with the placeholder)
Look for any deferred nodes
Automatically create a remote request for the missing node
show.js
show.js
No changes to the original show.js
component. We don't even have to create a conditional, the initial page response will contain a placeholder.
Last updated