[tutorial errata]
- Part 1 / Stores / Store bindings
- tutorial
- git
- comments:
- following:
- The
$name += '!'assignment is equivalent toname.set($name + '!').
- The
- addition:
- a note that this is also equivalent to:
name.update(n => n + '!') - a note about whether this is also equivalent to:
name.update($name => $name + '!')- does
$namehave any special meaning in this context,
or can it be used (for readability) as the name of this parameter?
- does
- a note about whether there is any performance benefit in choosing one form vs. another
- a note that this is also equivalent to:
- following:
I don't know that these sorts of things belong at this point in the tutorial. To answer some of these specific points: It's only equivalent to name.update(n => n + '!') if your store also implements the .update() method. The stores created by the exports from svelte/store so, but this is not guaranteed by the store contract. $name += '!' compiles to name.set($name + '!') which is guaranteed to work for all stores that satisfy the contract.
$name does not have special meaning when it's been shadowed by a local variable like a function parameter.
.set might be microscopically faster, but I don't think it would make any difference in the context of a real application.
- Part 2 / Advanced bindings / Contenteditable bindings
- tutorial
- git
- comments:
- I may be nitpicking..
but I believe that this example doesn't fully illustrate the concept - am I wrong to think that a better example might be:
<script> let html = '<p>Write <b><i>some</i></b> text!</p>'; </script> <div bind:textContent={html} contenteditable /> <div>{@html html}</div> <style> [contenteditable] { padding: 0.5em; border: 1px solid #eee; border-radius: 4px; margin-bottom: 1em; } </style>
- I may be nitpicking..
- Part 3 / Routing / Pages
- tutorial
- git:
- comments:
- the theme configured for the tutorial is always used by the sample app that is rendered in an iframe
- the tutorial allows the user to specify the relative URL (ie: route) that is rendered by the app
- this relative URL should allow the user to override the global theme by specifying a
?theme=querystring parameter- ex:
/about?theme=dark
- ex:
- however, this querystring value is updated by
set_iframe_srcimmediately before the iframe is rendered
- suggestion:
/** @param {string} src */ function set_iframe_src(src) { if (!iframe) return; // HMR // To prevent iframe flickering. // Set to `visible` by calling `set_iframe_visible` function // from iframe on:load or setTimeout iframe.style.visibility = 'hidden'; setTimeout(set_iframe_visible, 1000); // removing the iframe from the document allows us to // change the src without adding a history entry, which // would make back/forward traversal very annoying const parentNode = /** @type {HTMLElement} */ (iframe.parentNode); parentNode?.removeChild(iframe); const url = new URL(src); if (!url.searchParams.has('theme')) url.searchParams.set('theme', $theme.current); iframe.src = url.href; parentNode?.appendChild(iframe); } - where:
- the only change is the addition of a conditional test:
if (!url.searchParams.has('theme'))
before updating the theme querystring parameter
- the only change is the addition of a conditional test:
- Part 3 / Shared modules / The
$libalias
update:
- nevermind..
I commented before reading far enough to learn that this error was intentional
note (to self):
- Part 3 / Forms / Validation
- tutorial
- comments:
+page.server.jsexport const actions = { create: async ({ cookies, request }) => { return {success: 'saved OK'} }, delete: async ({ cookies, request }) => { return {success: 'removed OK'} } }+page.svelte<script> export let form; </script> {#if form?.success} <p class="error">{form.success}</p> {/if}
note (to self):
- Part 3 / Forms / Customizing
use:enhance- tutorial
- comments:
+page.server.jsimport {fail} from '@sveltejs/kit' export const actions = { delete: async () => { await new Promise((fulfil) => setTimeout(fulfil, 1000)) return fail(500, { error: 'Database Error' }) } }
note (to self):
- Part 3 / Stores / page
- tutorial
- comments:
src/routes/+layout.svelte<script> import { page } from '$app/stores'; const nav = [{ name: 'home', path: '/' },{ name: 'about', path: '/about' }] </script> <nav> {#each nav as item} <a href="{item.path}" aria-current={$page.url.pathname === item.path}> {item.name} </a> {/each} </nav> <slot />
note (to self):
- Part 3 / Stores / navigating
- tutorial
- comments:
src/routes/+layout.svelte<script> import { page, navigating } from '$app/stores'; $: console.log( JSON.stringify($page, null, 2) ); $: console.log( JSON.stringify($navigating, null, 2) ); </script>
note (to self):
- Part 4 / Hooks /
handle- tutorial
- comments:
src/hooks.server.jsimport { redirect } from '@sveltejs/kit'; export async function handle({ event, resolve }) { console.log( JSON.stringify(event, null, 2) ); switch(event.url.pathname) { case '/ping': throw redirect(307, '/pong') case '/pong': return new Response('pong') } return await resolve(event) }
note (to self):
- Part 4 / Hooks /
handleFetch
- tutorial
- comments:
src/hooks.server.jsexport async function handleFetch({ event, request, fetch }) { console.log('01. ' + (typeof event.request === typeof request)) console.log('02. ' + (typeof event.fetch === typeof fetch)) console.log('03. ' + (typeof event.request.url === typeof request.url)) console.log('04. ' + (event.request === request)) console.log('05. ' + (event.fetch === fetch)) console.log('06. ' + (event.request.url === request.url)) console.log('07. typeof event.url => ' + (typeof event.url) + ((event.url instanceof URL) ? ' (instanceof URL)' : '')) console.log('08. typeof request.url => ' + (typeof request.url) + ((request.url instanceof URL) ? ' (instanceof URL)' : '')) console.log('09. event.request.url => ' + event.request.url) console.log('10. request.url => ' + request.url) return await fetch(request); }- logs:
01. true 02. true 03. true 04. false 05. false 06. false 07. typeof event.url => object (instanceof URL) 08. typeof request.url => string 09. event.request.url => http://localhost:5173/?theme=light 10. request.url => http://localhost:5173/a
note (to self):
- Part 4 / Page options /
trailingSlash
- tutorial
- comments:
src/routes/+layout.svelte<nav> <a href="/always">/always</a> <a href="/always/">/always/</a> <a href="/ignore">/ignore</a> <a href="/ignore/">/ignore/</a> <a href="/never">/never</a> <a href="/never/">/never/</a> </nav> <slot /> <hr /> <h3>themes:</h3> <ul data-sveltekit-reload> <li><a href="./?theme=dark">dark</a></li> <li><a href="./?theme=light">light</a></li> </ul>
- Part 4 / Advanced routing / Breaking out of layouts
- tutorial
- example given:
src/routes/a/b/c/[email protected]- uses:
src/routes/+layout.svelte
- ignores:
src/routes/a/b/c/+layout.svelte
- uses:
- comments:
- the individual page resets its layout hierarchy to the root layout
- should it not then also inherit the layout in its own directory?
- questions:
- can a layout hierarchy be reset for all descendent pages?
- example:
src/routes/a/b/c/[email protected]src/routes/a/b/c/+page.svelte- such that it uses:
src/routes/+layout.sveltesrc/routes/a/b/c/[email protected]
- such that it uses:
src/routes/a/b/c/d/+layout.sveltesrc/routes/a/b/c/d/+page.svelte- such that it uses:
src/routes/+layout.sveltesrc/routes/a/b/c/[email protected]src/routes/a/b/c/d/+layout.svelte
- such that it uses:
- example:
- can a layout hierarchy be reset for all descendent pages?
- Docs: CORE CONCEPTS / Loading data / Using parent data
- docs
- git
- comments:
- fair warning… to avoid waterfalls
- the given implementation does not do that
- 2 Promises are resolved synchronously
- the order doesn't matter
- a better implementation might more closely resemble:
export async function load({ params, parent }) { const [parentData, data] = await Promise.all([ parent(), getData(params) ]); return { ...data meta: { ...parentData.meta, ...data.meta } }; }
note (to self):
- Part 4 / Environment variables /
$env/static/private
- tutorial
- comments:
src/routes/+page.server.jsimport * as env from '$env/static/private'; console.log(JSON.stringify(env, null, 2));