Web-Apps with Svelte
A Practical Introduction

The Trainer
- Nils Röhrig
- Software Engineer @ Loql
- Frontend focus
- Svelte user since 2019
- Speaker at conferences and meetups

Agenda
Part II
- Nesting
- Props
- Component Slots
- Event Dispatching
- Event Forwarding
- Events vs. Callbacks
Part I
- Framework
- Local State
- Directives
- Control Structures
- CSS Support
- SVG Support
- Reactivity
Part III
- Svelte Stores
- Custom Stores
- Svelte Context
- Stores in Context
Part IV
- Working with Promises
- Transitions
- Svelte Actions
- DOM References
Coffee Break
10:00 - 10:30
Lunch Break
12:00 - 13:00
Coffee Break
14:30 - 15:00
Agenda
Teil II
- Verschachtelung
- Props
- Komponenten- Slots
- Event Dispatching
- Event Forwarding
- Events oder Callbacks
Teil I
- Framework
- Lokaler State
- Direktiven
- Kontrollstrukturen
- CSS Support
- SVG Support
- Reaktivität
Teil III
- Svelte Stores
- Custom Stores
- Svelte Kontext
- Stores im Kontext
Teil IV
- Arbeit mit Promises
- Transitionen
- Svelte Actions
- DOM-Referenzen
Kaffepause
10:30 - 11:00
Mittagspause
12:30 - 13:30
Kaffepause
15:00 - 15:30
Part I
Teil I
- Framework
- Local State
- Directives
- Control Structures
- CSS Support
- SVG Support
- Reactivity
Svelte is a tool for building web applications. Like other user interface frameworks, it allows you to build your app declaratively out of components that combine markup, styles and behaviours.
Svelte is a component framework
Svelte is a component framework
Logo
Register
Home
E-Mail
Submit
etc. pp...
Component
Component
Component
These components are compiled into small, efficient JavaScript modules that eliminate overhead traditionally associated with UI frameworks.
Svelte is a compiler
Svelte is a compiler
<h1>Simple Component</h1>Component.svelte
Svelte is a compiler
<h1>Simple Component</h1>Svelte is a compiler
<h1>Simple Component</h1>Svelte is a compiler
<h1>Simple Component</h1>import { SvelteComponent, detach, element, init,
         insert, noop, safe_not_equal } from "svelte/internal";
function create_fragment(ctx) {
  let h1;
  return {
    c() {
      h1 = element("h1");
      h1.textContent = "Simple Component";
    },
    m(target, anchor) {
      insert(target, h1, anchor);
    },
    p: noop,
    i: noop,
    o: noop,
    d(detaching) {
      if (detaching) detach(h1);
    },
  };
}
class SimpleComponent extends SvelteComponent {
  constructor(options) {
    super();
    init(this, options, null, create_fragment, safe_not_equal, {});
  }
}
export default SimpleComponent;Svelte is a compiler
<h1>Simple Component</h1>import { [...] } from "svelte/internal";
function create_fragment(ctx) {
  let h1;  
  return {
    c() {
      h1 = element("h1");
      h1.textContent = "Simple Component";
    },
    m(target, anchor) {
      insert(target, h1, anchor);
    },
    p: noop, i: noop, o: noop,
    d(detaching) { if (detaching) detach(h1); },
  };
}
class Component extends SvelteComponent {
  constructor(options) {
    super();
    init(this, options, null, create_fragment, 
		safe_not_equal, {});
  }
}
export default Component;
Component.js
Svelte is a compiler
<h1>Simple Component</h1>import Component from "./Component.js";
const app = new Component({
  target: document.body,
});
export default app;
main.js
Anatomy of a component
Anatomy of a component
<script>
  // STATE & BEHAVIOR
</script>
<!-- DECLARATIVE MARKUP -->
<h1>Hello enterJS!</h1>
<p>{"Put your JS expressions in curly braces."}</p>
<style>
  /* PRESENTATION */
</style>Component.svelte
Local State
Local State
- The local component state in Svelte consists of local variables.
 
- It describes the state of the component and is not shared with other components.
 
- The local state is reactive in the Svelte sense, meaning that only the affected parts of the component are updated when changes occur.
Directives
Directives
- Svelte directives can be used as attributes in Svelte elements.
 
- They can control the behavior of elements, such as binding data or handling events.
 
- Svelte provides various directives that can control the behavior of elements, such as on:andbind:.
Control Structures
Control Structures
- Control structures are an integral part of Svelte markup.
 
- They control the program flow and are known from other programming languages.
 
- Svelte provides a block syntax for control structures that supports various expressions like if,else,each, and others.
Changing the value of an {#each} block
Changing the value of an {#each} block
- If the value of an {#each}block in Svelte is changed, elements are removed or added only at the end of the block.
 
- Changed elements are updated at the same position in the DOM.
 
- Using unique IDs can avoid unwanted effects if rendered elements are not directly or reactively dependent on the change of the value.
Keyed Each Block
Local Constants
Reactivity
Reactivity
- Svelte integrates reactivity as a core element.
 
- The =operator and its variants are used in Svelte to establish data binding between variables and UI elements.
 
- Svelte tracks dependencies between variables and only updates the parts of the DOM that are affected by them.
 
- By tracking assignments at build time, the code is optimized.
 
- Svelte provides language support such as Reactive Statements.
CSS Support
CSS Support
- CSS is part of the Single-File-Component approach in Svelte.
 
- Styles are automatically scoped to avoid conflicts.
 
- Directives allow for binding of classes.
 
- There are also directives for selectively setting individual CSS properties.
SVG Support
SVG Support
- Svelte offers full support for SVG graphics.
 
- SVG elements can be directly included in Svelte components.
 
- Svelte allows for dynamically updating SVG attributes and properties.
Live Coding
Exercise
Exercise
- Add filters for transactions:
	- All time: All transactions
- Monthly: Current month
- Weekly: Current calendar week
 
- The filtering should be reflected in
	- the StatCards
- the transaction table
 
Notes
- The implementation method is freely selectable
- Modules in src/lib can be used
Tasks
git checkout tags/part_1_exercise -b <BRANCH_NAME>
npm ci
npm run devPreparation
Repository
Proposed Solution
Part II
Part II
- Nesting
- Props
- Component Slots
- Event Dispatching
- Event Forwarding
- Events vs. Callbacks
Nesting of components
Nesting of components
E-Mail
Submit
Register
Home
Logo
Nesting of components
E-Mail
Submit
Register
Home
Logo
Logo
Register
Home
E-Mail
Submit
Logo
Register
Home
E-Mail
Submit
Logo
Register
Home
E-Mail
Submit
E-Mail
Submit
Register
Home
Logo
Logo
Register
Home
E-Mail
Submit
Logo
Register
Home
E-Mail
Submit
E-Mail
Submit
Register
Home
Logo
<Logo>
<Header>
<App>
<NavItem>
<NavItem>
<NavBar>
<Label>
<Input>
<Form>
<Button>
Props
Props
Register
Home
Props
<NavItem>
<NavItem>
Register
Home
Props
<NavItem >
<NavItem >
label="Home"
label="Register"
Register
Home
Props
<script>
    const str = "a string";
    const num = 12345;
    const bool = true;
    const obj = {key: "value"};
    const arr = [1, 2, 3, 4, 5];
    
    function callback() {
        console.log("callback");
    }
</script>
<AnyComponent 
    stringProp={str}
    numberProp={num}
    booleanProp={bool}
    objectProp={obj}
    arrayProp={arr}
    {callback} 
/>
Props
<script>
    const str = "a string";
    const num = 12345;
    const bool = true;
    const obj = {key: "value"};
    const arr = [1, 2, 3, 4, 5];
    
    function callback() {
        console.log("callback");
    }
</script>
<AnyComponent 
    stringProp={str}
    numberProp={num}
    booleanProp={bool}
    objectProp={obj}
    arrayProp={arr}
    {callback} 
/>
<script>
  export let stringProp = "";
  export let numberProp = 0;
  export let booleanProp = true;
  export let objectProp = {key: "value"};
  export let arrayProp = [1, 2, 3];
  export let callback = () => undefined;
</script>
<p>{stringProp}</p>
<p>{numberProp}</p>
<p>{booleanProp}</p>
{#each Object.entries(objectProp) as [key, value]}
  <p>{key}: {value}</p>
{/each}
{#each arrayProp as value}
  <p>{value}</p>
{/each}
<button on:click={callback}>Call back</button>$$props & $$restProps
Event Dispatching
Event Dispatching
E-Mail
Submit
Register
Home
Logo
Event Dispatching
E-Mail
Submit
Logo
Register
Home
E-Mail
Submit
<App>
<Form>
Event Dispatching
E-Mail
Submit
Logo
Register
Home
E-Mail
Submit
<App>
<Form>
How?
Event Dispatching
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
  
  async function submitForm() {
    await postForm();
    dispatch("form:posted", { /* any information to share */ });
  }
</script>
<form on:submit={submitForm}>
  <!-- form content -->
</form>Form.svelte
Event Dispatching
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
  
  async function submitForm() {
    await postForm();
    dispatch("form:posted", { /* any information to share */ }
  }
</script>
<form on:submit={submitForm}>
  <!-- form content -->
</form>Form.svelte
<script>
  import Form from './Form.svelte';
  
  function handleSubmit(event) {
    
    /* here the shared information can be found, 
     * as Svelte events are just instances of 
     * CustomEvent */
    const { detail } = event;
    console.log({detail});
  }
</script>
<Form on:form:posted={handleSubmit} />App.svelte
Event Forwarding
Event Forwarding
- Event forwarding forwards events from child components to parent components.
 
- This allows parent components to react to user actions in their child components.
 
- It promotes coordination of data and actions across the component hierarchy.
Event Forwarding
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
  
  async function submitForm() {
    await postForm();
    dispatch("submit", { /* any information to share */ }
  }
</script>
<form on:submit={submitForm}>
  <!-- form content -->
</form>Form.svelte
<script>
  import Form from './Form.svelte';
  
  function handleSubmit(event) {    
    /* here the shared information can be found, 
     * as Svelte events are just instances of 
     * CustomEvent */
    const { detail } = event;
    console.log({detail});
  }
</script>
<Form on:submit={handleSubmit} />App.svelte
Event Forwarding
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
  
  async function submitForm() {
    await postForm();
    dispatch("submit", { /* any information to share */ }
  }
</script>
<form on:submit={submitForm}>
  <!-- form content -->
</form>Form.svelte
<script>
  import Form from './Form.svelte';
  
  function handleSubmit(event) {    
    /* here the shared information can be found, 
     * as Svelte events are just instances of 
     * CustomEvent */
    const { detail } = event;
    console.log({detail});
  }
</script>
<Form on:submit={handleSubmit} />App.svelte
Event Forwarding
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
  
  async function submitForm() {
    await postForm();
    dispatch("submit", { /* any information to share */ }
  }
</script>
<form on:submit={submitForm}>
  <!-- form content -->
</form>Form.svelte
<script>
  import Form from './Form.svelte';
  
  function handleSubmit(event) {    
    /* here the shared information can be found, 
     * as Svelte events are just instances of 
     * CustomEvent */
    const { detail } = event;
    console.log({detail});
  }
</script>
<Form on:submit={handleSubmit} />App.svelte
Event Forwarding
<form on:submit>
  <!-- form content -->
</form>Form.svelte
<script>
  import Form from './Form.svelte';
  
  async function handleSubmit(event) {
    const data = new FormData(event.target);
    await postData(data);
  }
</script>
<Form on:submit={handleSubmit} />App.svelte
Events vs. Callbacks
Events vs. Callbacks
<script>
  import AnotherComponent from './AnotherComponent.svelte';
  
  function callback() {
    console.log("I am a callback. Arguments: ", ...arguments);
  }
</script>
<AnotherComponent {callback} /><script>
  export let callback;
</script>
<button on:click={callback}>
  Click me!
</button>Component.svelte
AnotherComponent.svelte
Events vs. Callbacks
<script>
  import Button from './Button.svelte';
  
  function handleButtonElementClick() {
    console.log("Button element clicked.");
  }
  
  function handleButtonComponentClick() {
    console.log("Button component clicked.");
  }
</script>
<button on:click={handleButtonElementClick}>Button element</button>
<Button onClick={handleButtonComponentClick}>Button Component</Button>Component Slots
Component Slots
- Slots in Svelte allow for the dynamic injection of content into components.
 
- They are defined in components using the <slot>element.
 
- Slot contents are provided by parent components.
 
- Slot contents can contain any valid Svelte markup.
Component Slots
Dialog
Text that is shown in the dialog. Potentially expanded by further content.
Okay
Component Slots
<strong>Dialog</strong>
<p>Text that is shown in the dialog. Potentially expanded by further content.</p>
<button>Okay</button>
Live Coding
Exercise
Exercise
- Create a detail page for transactions
 
- The detail page should contain all information about a transaction
 
- On each detail page, the respective transaction can be deleted
	
Notes
- The implementation method is freely selectable
 
- The example app uses modified StatCards
Tasks
Repository
git checkout tags/part_2_exercise -b <BRANCH_NAME>
npm ci
npm run devPreparation
Proposed Solution
Part III
Part III
- Svelte Stores
- Custom Stores
- Svelte Context
- Stores in Context
Svelte Stores
Svelte Stores
- Stores are JavaScript objects that encapsulate values and can be subscribed to using the .subscribemethod.
 
- Subscribers are notified of updates.
 
- Svelte provides language support for using stores.
 
- There are different types of built-in stores, namely readable,writable, andderived.
Svelte Store Contract
Svelte Store Contract
- A Store must contain a .subscribemethod that accepts a subscription function as an argument to create a subscription.
 
- The subscription function must be called immediately and synchronously with the current value of the Store when .subscribeis called.
 
- All active subscription functions of the Store must be called synchronously later when the value of the Store changes.
 
- 
.subscribemust return an unsubscribe function. Calling it must end the subscription and the corresponding subscription function must not be called again by the Store.
 
- A store can optionally include a .setmethod, which accepts a new value as an argument and updates the store with it. Such a store is referred to as a writable store.
Custom Stores
Svelte Context
Svelte Context
- The context is a key-value store that enables data transfer from a component to all of its hierarchically subordinate components without explicit props.
 
- 
setContext()is used to create and provide the context in the parent component.
 
- 
getContext()is used to retrieve the context in the child components.
 
- The context can contain arbitrary values, such as configuration data, functions, or stores.
 
- The context is not reactive in the Svelte sense.
Stores in Context
Live Coding
Exercise
Exercise
- Create a mechanism for synchronizing transactions in the browser's local storage
	
Notes
- The type of implementation is up to you
 
- Stores can be subscribed to
Tasks
Repository
git checkout tags/part_3_exercise -b <BRANCH_NAME>
npm ci
npm run devPreparation
Proposed Solution
Part IV
Part IV
- Working with Promises
- Transitions
- Svelte Actions
- DOM References
Working with Promises
Working with Promises
Render Component
Fetch Data
Update View
Arbeit mit Promises
Render Component
Fetch Data
Update View

Transitions
Transitions
- Transitions in Svelte allow for animated transitions when adding or removing DOM elements.
 
- They are used through the transitiondirective and allow for the use of built-in or custom transitions.
 
- Svelte already includes transition effects such as fade,slide, orscale.
 
- Custom function effects follow a unified interface, which can be found in the Svelte documentation.
Transitionen



Refs & Actions
Refs & Actions
- Refs are a way to reference DOM elements.
 
- They are created using the bind:this={variable}directive and can be used and shared like other variables.
 
- Actions are functions that can be directly attached to DOM elements without creating an explicit reference.
 
- They are used with the use:actionName={params}directive.
 
- Actions are executed when added to the DOM.
 
- They can optionally return a function that is executed when removed from the DOM.
Live Coding
Übung
Exercise
- Create a visualization for income and expenses using Chart.js
	
Notes
- Chart.js is already listed in the dependencies
 
- Use Svelte Actions to bring visualizations into the DOM
 
- Chart type, implementation method, etc. are freely selectable
Tasks
Repository
git checkout tags/part_4_exercise -b <BRANCH_NAME>
npm ci
npm run devPreparation
LinkedIn:
Xing:
X:
Thank You!
Web-Apps with Svelte - A Practical Introduction (iJS Munich 2023)
By Nils Röhrig
Web-Apps with Svelte - A Practical Introduction (iJS Munich 2023)
- 2,355
 
   
   
  