Svelte pages
Pages are just svelte components located at www/pages
.
You can refer to these pages by their relative file names.
Note
The .svelte
extension is optional.
Example
A page located at www/page/welcome.svelte
will be identified by welcome
.
Subdirectories are joined by ::
instead of /
or \
.
Example
A page located at www/page/about/user.svelte
will be identified by about::user
.
Mapping a page
You can map pages with frz.ServerWithSveltePage()
frz.ServerWithSveltePage(server, "GET /welcome", "welcome", configure)
Mapping a page requires
- a pattern,
GET /welcome
in this case, - a page id,
welcome
in this case, - a configuration provider, called
configure
in this case.
This configuration provider is a function that must take in a request and return a configuration
func configure(_ *frz.Request) *frz.SveltePageConfiguration {
return &frz.SveltePageConfiguration{
Render: frz.ModeFull,
Data: map[string]interface{}{
"name": "world",
},
}
}
The resulting configuration defines a required Render
property, indicating the rendering mode,
which can be frz.ModeServer
, frz.ModeClient
or frz.ModeFull
and an optional Data
property, which can be retrieved by any of your components with getContext("data").
Note
See overview page for more details on rendering modes.
<script>
import { getContext } from "svelte";
const data = getContext("data")
</script>
<h1>Hello {data.name}</h1>
Note
Context data
is created with $state(), hence it is reactive.
Warning
Context keys query
, path
, and form
are reserved.
See next sections.
Query fields
Query fields are automatically injected in the context of the svelte page that's being rendered.
Say, for example, that you've mapped your svelte page to GET /about
and some client requests GET/about?name=world
.
You can retrieve the name
query field with getContext("data").query.name
.
// prepare/main.go
frz.PrepareSveltePage("about", "www/lib/pages/about.svelte")
// main.go
frz.ServerWithSveltePage(server, "GET /about", "about", configure)
<!--www/lib/pages/about.svelte-->
<script>
import { getContext } from "svelte";
const data = getContext("data")
</script>
<h1>Hello {data.query.name}</h1>
Path fields
Path fields are automatically injected in the context of the svelte page that's being rendered.
Say, for example, that you've mapped your svelte page to GET /about/{name}
.
You can retrieve the {name}
path field with getContext("data").path.name
.
// prepare/main.go
frz.PrepareSveltePage("about", "www/lib/pages/about.svelte")
// main.go
frz.ServerWithSveltePage(server, "GET /about/{name}", "about", configure)
<!--www/lib/pages/about.svelte-->
<script>
import { getContext } from "svelte";
const data = getContext("data")
</script>
<h1>Hello {data.path.name}</h1>
Form fields
Form fields are automatically injected in the context of the svelte page that's being rendered.
All incoming form fields are mapped into getContext("data").form
.
<script>
import { getContext } from "svelte";
const data = getContext("data")
</script>
<h1>Hello {data.form.name}</h1>
However, when dealing with forms, you will most likely want to update your state in-place, so for that reason it is best to configure each page individually.
Note
If you're coming from the MVC world, you can think of configuration providers as Controllers.
The following is a more in-depth example using form fields.
// prepare/main.go
frz.PrepareSveltePage("about", "www/lib/pages/about.svelte")
// main.go
// GET /about
frz.ServerWithSveltePage(server, "GET /about", "about",
func(_ *frz.Request) *frz.SveltePageConfiguration {
return &frz.SveltePageConfiguration{Render: frz.ModeFull}
},
)
// POST /about
frz.ServerWithSveltePage(server, "POST /about", "about",
func(request *frz.Request) *frz.SveltePageConfiguration {
form := frz.ReceiveForm(request)
name := form.Get("name")
if len(name) < 2 {
return &frz.SveltePageConfiguration{
Render: frz.ModeFull,
Data: map[string]interface{}{"error": "Name must be at least 2 characters long."},
}
}
return &frz.SveltePageConfiguration{
Render: frz.ModeFull,
Data: map[string]interface{}{"name": name},
}
},
)
<!--www/lib/pages/about.svelte-->
<script>
import { getContext } from "svelte";
const data = getContext("data")
</script>
{#if data.error}
<h3>Error</h3>
<span>{data.error}</span>
{:else if data.name}
<h3>Welcome, {data.name}!</h3>
{:else}
<form method="POST" action="?">
<label for="name">
<span>Name</span>
<input type="text" id="name" name="name" value="" />
</label>
<br/>
<button type="submit">Submit</button>
</form>
{/if}