Saving and reloading state #345
Answered
by
jourdain
banesullivan-kobold
asked this question in
Q&A
-
I'm working on an experiment to see if I can serialize Trame's state and re-populate the state. Here is a simple example. I'm running into an issue where anytime I try to serialize/save the state, Steps to reproduce my issue:
import json
import os
from trame.app import get_server
from trame.ui.vuetify import SinglePageWithDrawerLayout
from trame.widgets import html, leaflet, vuetify
server = get_server()
state, ctrl = server.state, server.controller
state.trame__title = "State I/O"
BASEMAPS = [
{
"text": "Open Street Map",
"value": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
},
{
"text": "Positron",
"value": "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
},
]
state["features"] = {
"a": {"visible": True, "coordinate": [36.817139835261855, -113.93558001830006]},
"b": {"visible": True, "coordinate": [35.76260704305611, -112.21926468995544]},
"c": {"visible": True, "coordinate": [33.76925058301366, -113.83006948312241]},
}
def save_state(*args, **kwargs):
with state:
state.flush()
print(state["features"]) # check console: does it match what I expect?
with open("state.json", "w") as f:
f.write(json.dumps(state.to_dict()))
def load_state(*args, **kwargs):
with open("./state.json", "r") as f:
state.update(json.loads(f.read()))
def update_visibility(*args, **kwargs):
# TODO: optimize to only mark the toggled variable
state.dirty("features")
with SinglePageWithDrawerLayout(server) as layout:
layout.title.set_text(state.trame__title)
with layout.toolbar:
layout.toolbar.style = "z-index: 1000;" # really bump it to be above leaflet
vuetify.VSpacer()
vuetify.VSelect(
label="Basemap",
v_model=("basemap_url", BASEMAPS[1]["value"]),
items=("array_list", BASEMAPS),
hide_details=True,
dense=True,
outlined=True,
classes="pt-1 ml-2",
style="max-width: 250px; padding: 10px;",
)
with vuetify.VBtn(icon=True, click=save_state):
vuetify.VIcon("mdi-content-save-outline")
with vuetify.VBtn(icon=True, click=load_state):
vuetify.VIcon("mdi-file-upload-outline")
with layout.drawer:
with html.Div(style="overflow: auto; width: 100%; height 100%;"):
with vuetify.VList(shaped=True, v_model=("selectedRoute", 0)):
vuetify.VSubheader("Features")
for feature in sorted(state["features"].keys()):
with vuetify.VListItem():
with vuetify.VListItemIcon():
vuetify.VIcon("mdi-map-marker-outline")
with vuetify.VListItemContent():
vuetify.VListItemTitle(feature)
vuetify.VCheckbox(
v_model=f"features.{feature}.visible",
on_icon="mdi-eye-outline",
off_icon="mdi-eye-off-outline",
dense=True,
hide_details=True,
classes="my-0 py-0 ml-1",
change=(update_visibility,),
)
with layout.content:
with vuetify.VContainer(
fluid=True,
classes="pa-0 fill-height",
):
with leaflet.LMap(zoom=("zoom", 5), center=("center", (34.792, -111.769))):
leaflet.LTileLayer(
url=(
"basemap_url",
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
),
attribution=(
"attribution",
'© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors',
),
)
for feature in state["features"].keys():
leaflet.LMarker(
lat_lng=(f"features.{feature}.coordinate",),
visible=(f"features.{feature}.visible",),
)
if __name__ == "__main__":
# Load state from file on start-up
if os.path.exists("./state.json"):
...
server.start() |
Beta Was this translation helpful? Give feedback.
Answered by
jourdain
Sep 27, 2023
Replies: 1 comment 3 replies
-
This problem seems to only occur with nested variables (i.e., |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I was going to say that you seem to be editing nested variables on the client side without forcing them to be sent back to the server by calling
flushState('features')
.Just bind
flushState('features')
on an event that gets triggered by the UI that edits its internal state.