The web platform gives you several tools to persist state across requests, like cookies or session storage.
But with overlays you need to store state per layer.
Unpoly adds layer context, a key/value store that exists for the lifetime of a layer:
Store | Scope | Persistence | Values | Client-manageable | Server-manageable |
---|---|---|---|---|---|
Local storage | Domain | Permanentish | String | Yes | – |
Cookies | Domain | Configurable | String | Configurable | Yes |
Session storage | Tab | Session | String | Yes | – |
Unpoly context | Layer | Session | Object | Yes | Yes |
The default context is an empty object ({}
).
You may initialize the context object when opening a layer:
up.layer.open({ url: '/games/new', context: { lives: 3 } })
Or from HTML:
<a href='/games/new' up-layer='new' up-context='{ "lives": 3 }'>
Start a new game
</a>
You may read and change the context from your client-side JavaScript:
up.layer.on('heart:collected', function() {
up.context.lives++
})
You may read and change the context from the server:
class GamesController < ApplicationController
def restart
up.context[:lives] = 3
render 'stage1'
end
end
Context is useful when you want to re-use an existing interaction in an overlay, but make a slight variation.
Assume you want to re-use your existing /contacts
list for a contact picker widget. The contact picker opens the context index in an overlay where the user can choose a contact.
In this case the contact index should show an additional message "Pick a contact for project Foo", replacing Foo
with the actual name of the project.
We can implement such an contact picker with this ERB template:
<% form_for @project do |form| %>
Contact: <%= form.object.contact %>
<a href='/contacts'
up-layer='new'
up-accept-location='/contacts/*'
up-context='<%= { project: @project.name }.to_json %>'>
Pick a contact
</a>
...
<% end %>
Our effective contact object would now be something like { project: 'Hosting 2021' }
.
When rendering the /contacts
the server can access the current layer context through the X-Up-Context
header.
It can then decide to render a different title:
<% if up.context[:project] %>
Pick a contact for <%= up.context[:project] %>
<% else %>
List of contacts
<% end %>
<% @contacts.each do |contact| %>
<li>...</li>
<% end %>
Note
Request headers that influenced a response should be listed in a
Vary
response header. This tells Unpoly to partition its cache for that URL so that each request header value gets a separate cache entries.