Svelte for Angular Developers
Tags: javascript, svelte, webdev, angular
Published: 2019-10-05 10:42:00

## A simple introduction to Svelte from an Angular developer’s perspective

*This article was originally published on [Bits and Pieces](https://blog.bitsrc.io) by [Giancarlo Buomprisco](https://medium.com/@.gc)*

[Svelte](https://svelte.dev/) is a relatively recent framework for building UIs developed by Rich Harris, also the creator of Rollup.

Svelte will likely appear as **a radically different approach** from what you’ve seen before, and that’s probably a good thing.

Svelte will impress you for mainly two things: **its speed, and its simplicity**. In this article, we’ll focus on the latter.

As my main expertise revolves around Angular, it is only normal that I try to learn it by replicating the approaches I’m used to with the former by using Svelte. And this is what this article is going to be about: how to do *Angular* things — but with *Svelte*.
***
**Useful tip:** Use [**Bit](https://bit.dev?utm_medium=content&utm_source=bitsandpieces&utm_content=1&utm_campaign=campaign)** to **encapsulate components with all their dependencies** and setup. Build truly modular applications with better code reuse, simpler maintenance, and less overhead.

***
**Note**: Although I will be expressing my preferences, this is not a comparison: it is a simple and quick introduction to Svelte for people who use Angular as a framework of choice.

**Spoiler Alert**: Svelte is fun.

## Components 📦

In Svelte every component corresponds to its relative file: for instance, the component Button will be created by naming its file Button.svelte. Of course, we normally do the same in Angular, but it is purely a convention.

Svelte components are written using a single-file convention, and it is made of 3 sections: script, style, and the template, which doesn’t have to be wrapped within its specific tag.

Let’s create a dead-simple component that renders “Hello World”.

![](https://cdn-images-1.medium.com/max/2258/1*WS1eWXq_DLo2_yp6X9lZtA.png)

### Importing Components

This is mostly the same as if you were importing a JS file, with an only difference:

* you need to explicitly reference the components with the .svelte extension

* it’s important to notice that you will need to import Svelte components from within the script section

```html
    <script>
      import Todo from './Todo.svelte';
    </script>

    <Todo></Todo>
```

💡It is clear from the snippets above that **the number of lines to create a component in Svelte is incredibly low**. There’s a lot of implicitness and constraints there, of course, yet it is simple enough to get quickly used to it. Nicely played.

## Basic Syntax 📕

### Interpolations

Interpolations in Svelte are more similar to React than they are to Vue or Angular:

```html
    <script>
      let someFunction = () => {...}

    </script>

    <span>{ 3 + 5 }</span>
    <span>{ someFunction() }</span>
    <span>{ someFunction() ? 0 : 1 }</span>
```
I am quite used to typing twice the curly brackets that sometimes I make simple mistakes, but that’s just me.

### Attributes

Passing attributes to components is also fairly easy, there’s no need for quotes and can even be Javascript expressions:
```html
    // Svelte
    <script>
      let isFormValid = true;
    </script>

    <button disabled={!isFormValid}>Button</button>
```

### Events

The syntax for listening to events is on:event={handler}.
```html

    <script>
      const onChange = (e) => console.log(e);
    </script>

    <input on:input={onChange} />
```
As you may notice, opposite to Angular we don’t need to call the functions using parenthesis. To pass arguments to the function with could simply define an anonymous function:
```html

    <input on:input={(e) => onChange(e, ‘a’)} />
```
In terms of readability, I am in two minds:

* typing less, as we do not need brackets and quotes, is always a good thing

* readability-wise, I always liked Angular better than React, and as a result, to me is slightly more readable than Svelte. With that said, once again, I am very used to it and therefore my view here is biased

### Structural Directives

Contrary to Vue and Angular, Svelte provides a special syntax for looping and control flow within templates rather than using structural directives:

```html
    {#if todos.length === 0}
      No todos created
    {:else}
      {#each todos as todo}
        <Todo {todo} /> 
      {/each}
    {/if}
```

**I like this a lot**. No need to create HTML nodes, and readability-wise it does look awesome. Unfortunately my Macbook’s UK keyboard places # in a difficult to-reach-spot, which is making my experience with it a bit clunky.

### Inputs

Setting and getting properties (or @Input) from other components is as easy as exporting a constant from a script. Alright, that can be 
confusing — let’s write an example and see how easy it is:
```html
    <script>
      export let todo = { name: '', done: false };
    </script>

    <p>
      { todo.name } { todo.done ? '✅' : '❌' }
    </p>
```
* As you may have noticed, we initialized todo with a value: that will be the default value if the consumer will not provide a value for the input

Next, we create the container component that will pass the data down:
```html
    <script>
     import Todo from './Todo.svelte';

     const todos = [{
      name: "Learn Svelte",
      done: false
     },
     {
      name: "Learn Vue",
      done: false
     }];
    </script>

    {#each todos as todo}
      <Todo todo={todo}></Todo>
    {/each}
```
Similarly to plain JS, todo={todo} can be shortened and written as follows:
```html
    <Todo {todo}></Todo>
```
At first, I thought it was crazy, and now I think it is genial.

### Outputs

To create an@Output, i.e. a notification from child components to their parents, we will be using Svelte’s createEventDispatcher.

* We import the function createEventDispatcher and assign its return value to a variable called dispatch

* We call dispatch with two arguments: its name, and its payload (or “detail”)

* **Notice**: we add a function on click events (on:click) that will call the function markDone
```html
    <script>
     import { createEventDispatcher } from 'svelte';

     export let todo;
     
     const dispatch = createEventDispatcher();
     
     function markDone() {
      dispatch('done', todo.name);
     }
    </script>

    <p>
     { todo.name } { todo.done ? '✅' : '❌' } 
     
     <button on:click={markDone}>Mark done</button>
    </p>
```
The container component will need to provide a callback for the event dispatched, so that we can mark that todo object as “done”:

* we create a function called onDone

* we assign the function to the component’s event that we called done.
The syntax is on:done={onDone}
```html
    <script>
     import Todo from './Todo.svelte';
     
     let todos = [{
      name: "Learn Svelte",
      done: false
     },
     {
      name: "Learn Vue",
      done: false
     }];
     
     function onDone(event) {
      const name = event.detail;

    todos = todos.map((todo) => {
       return todo.name === name ? {...todo, done: true} : todo;
      });
     }
    </script>

    {#each todos as todo}
      <Todo {todo} on:done={onDone}></Todo>
    {/each}
```
**Notice**: to trigger a *change detection*, we **do not mutate the object**. Instead, we reassign the array todos and replace the todo marked as done.

💡**That is why Svelte is considered truly *reactive***: by simply reassigning the variable, the view will re-render accordingly.

### ngModel

Svelte provides a special syntax bind:<prop>={value} for binding certain variables to a component’s attributes and keep them in sync.

In different words, it allows for two-way data binding:
```html
    <script>
      let name = "";
      let description = "";

      function submit(e) {  // submit }
    </script>

    <form on:submit={submit}>
      <div>
        <input placeholder="Name" bind:value={name} />
      </div>

      <div> 
        <input placeholder="Description" bind:value={description} />
      </div>

      <button>Add Todo</button>
    </form>
```
## Reactive Statements 🚀

As we’ve seen before, Svelte reacts to an assignment and re-renders the view. To react to a change from another value, we can use reactive statements so that another value can automatically change in its turn.

For instance, let’s create a variable that will display whether all the todos have been checked:
```html
    let allDone = todos.every(({ done }) => done);
```
Unfortunately, though, the view will not be rendered because we never reassign allDone. Let’s replace this with a reactive statement, that makes us of Javascript “labels”:
```html
    $: allDone = todos.every(({ done }) => done);
```
Oh! That’s exotic. And before you shout “that’s too magic!”: did you know that labels are **valid Javascript**?

Let’s take a look at a demo:

![](https://cdn-images-1.medium.com/max/3036/1*EhAvR-2pEqlpTXZewxjWhw.gif)

## Content Projection

Content Projection also uses slots, which means you can name a slot and project it wherever you want within your component.

To simply interpolate all the content passed as content to your component, you can simply use the special element slot:
```html
    // Button.svelte
    <script>
        export let type;
    </script>

    <button class.type={type}>
     <slot></slot>
    </button>

    // App.svelte
    <script>
      import Button from './Button.svelte';
    </script>

    <Button>
      Submit
    </Button>
```
As you can see, the string “Submit” will take the place of <slot></slot>. *Named slots* require us to assign a name to a slot:
```html
    // Modal.svelte
    <div class='modal'>
     <div class="modal-header">
       <slot name="header"></slot>
     </div>
     
     <div class="modal-body">
      <slot name="body"></slot>
     </div>
    </div>

    // App.svelte
    <script>
      import Modal from './Modal.svelte';
    </script>

    <Modal>
     <div slot="header">
      Header
     </div>
     
     <div slot="body">
      Body
     </div>
    </Modal>
```
## Lifecycle Hooks

Svelte provides 4 lifecycle hooks, that are imported from the svelte package.

* **onMount**, a callback that runs when the component gets mounted

* **beforeUpdate**, a callback that runs **before** the components updates

* **afterUpdate**, a callback that runs **after** the components updates

* **onDestroy**, a callback that runs when the component gets destroyed

onMount is a function that accepts a callback that will be called when the component is mounted on the DOM. In short, it can be associated to ngOnInit.

If you return a function from the callback, this will be called when the component is unmounted.
```html
    <script>

    import { 
      onMount, 
      beforeUpdate, 
      afterUpdate, 
      onDestroy 
    } from 'svelte';

    onMount(() => console.log('Mounted', todo));
    afterUpdate(() => console.log('Updated', todo));
    beforeUpdate(() => console.log('Going to be updated', todo));
    onDestroy(() => console.log('Destroyed', todo));

    </script>
```
💡It’s important to notice that when onMount is called, its inputs have already been initialized. That means, todo is already defined when we log it in the snippet above.

## State Management

State Management is Svelte is incredibly fun and easy, and probably the aspect I like the most about it. Forget Redux’s boilerplate, and let’s see how to build a store that will allow us to store and manipulate our todos.

### Writable Store

The first thing we can do is to import writable from the package svelte/store and pass to the function the initial state
```html
    import { writable } from 'svelte/store';

    const initialState = [{
      name: "Learn Svelte",
      done: false
    },
    {
      name: "Learn Vue",
      done: false
    }];
     
    const todos = writable(initialState);
```
Normally, I’d store this in a file called todos.store.js and export the writable store so that the container component can update it.

As you may have noticed, todos is now a writable object and not an array. To retrieve the value of the store, we are going to use some Svelte magic:

* by prepending the store name with $ we can directly access the value of the store!

💡That means, all the references to todos will now be $todos:
```html
    {#each $todos as todo}
      <Todo todo={todo} on:done={onDone}></Todo>
    {/each}
```
### Setting State

A writable store’s state can be set by calling the method set which will imperatively set the state to the value passed:
```html
    const todos = writable(initialState);

    function removeAll() {
      todos.set([]);
    }
```
### Updating State

To update the store based on the current state, in our case the todos store, we can call the function update to which we pass a callback. The return value of the callback will be the new state passed to the store:

Let’s rewrite the function onDone that we defined above:
```html
    function onDone(event) {
      const name = event.detail;

      todos.update((state) => {
        return state.map((todo) => {
           return todo.name === name ? {...todo, done: true} : todo;
        });
      });
     }
```
Alright, I know, I wrote a reducer in the component. Not cool, you’re saying. Let’s move that to the store file, and export a function that simply takes care of updating the state.
```html
    // todos.store.js

    export function markTodoAsDone(name) {
      const updateFn = (state) => {
        return state.map((todo) => {
           return todo.name === name ? {...todo, done: true} : todo;
        });
      });

      todos.update(updateFn);
    }

    // App.svelte

    import { markTodoAsDone } from './todos.store';

    function onDone(event) {
      const name = event.detail;
      markTodoAsDone(name);
    }
```
### Listening to value changes

We can use the method .subscribe to listen to value changes from a store, . Notice, though, that the store is not an observable although the interface looks similar.
```html
    const subscription = todos.subscribe(console.log);

    subscription(); // unsubscribe subscription by calling it
```
💡 Svelte’s store package also provides two more utilities called readable and derivable.

## Observables 🦊

Oh, the part you were waiting for! You’ll be delighted to know that Svelte recently added support for RxJS and the ECMAScript Observable proposal.

As an Angular developer, I am quite used to working with reactive programming and not having something like the async pipe would be a bummer. But Svelte surprised me once again.

Let’s see how the two can work together: we’ll render a list of repositories from Github searched with the keyword “Svelte”.

You can paste the snippet below in the Svelte REPL and it will just work:
```html
    <script>
     import rx from "[https://unpkg.com/rxjs/bundles/rxjs.umd.min.js](https://unpkg.com/rxjs/bundles/rxjs.umd.min.js)";
     const { pluck, startWith } = rx.operators;
     const ajax = rx.ajax.ajax;
     
     const URL = `[https://api.github.com/search/repositories?q=Svelte`](https://api.github.com/search/repositories?q=Svelte`);
     
     const repos$ = ajax(URL).pipe(
        pluck("response"),
        pluck("items"),
        startWith([])
     );
    </script>

    {#each $repos$ as repo}
      <div>
        <a href="{repo.url}">{repo.name}</a>
      </div>
    {/each}

    // Angular's implementation
    <div *ngFor="let repo of (repos$ | async)>
      <a [attr.href]="{{ repo.url }}">{{ repo.name }}</a>
    </div>
```
💡 As you may have noticed, I prefixed the observable repos$ with $ and Svelte will automagically render it!

## My Svelte Wishlist 🧧

### Typescript support

As a Typescript enthusiast, I can’t help but wish for being able to write typed Svelte. I am so used to it that I keep typing my code, and then have to revert it. I do hope Svelte will soon add support for Typescript, as I suspect it is on everyone’s wishlist should they use Svelte from an Angular background.

### Conventions & Coding Guidelines

Being able to render in the view any variable in the script block is both powerful and, in my opinion, potentially messy. I am hoping the Svelte community will be working on a set of conventions and guidelines to help developers keep their files clean and understandable.

### Community Support

Svelte is a great project. With more community support such as third-party packages, backers, blog posts, etc. it can take off and become an established, further option to the awesome front-end landscape we’re enjoying nowadays.

## Final Words

Although I was not a fan of the previous version, I am fairly impressed with Svelte 3. It’s easy, small (yet exhaustive) and fun. It is so different that it reminds me of the first time when I transitioned from jQuery to Angular, and that’s exciting.

Whatever your framework of choice, learning Svelte will probably take a couple of hours. Once you figured out the basics and the differences with what you’re used to writing, writing Svelte is going to very easy.

***
If you need any clarifications, or if you think something is unclear or wrong, do please leave a comment!

*I hope you enjoyed this article! If you did, follow me on [Medium](https://medium.com/@.gc) or [Twitter](https://twitter.com/home) for more [articles](https://frontend.consulting/) about the FrontEnd, Angular, RxJS, Typescript and more!*