Svelte is not a framework like the other conventional Javascript frameworks. Svelte is an Ahead Of Time (AOT) compiler, so in the end the code that get shipped is just plain old Javascript with minimal runtime overhead. This is one of the reasons why Svelte is so fast, in some cases my entire Svelte application is smaller than the entire React library.

To use Svelte, you can install its cli tool or if you just want to experiment, you can make use of its online REPL. For our setup we will make use of the online REPL.

Lets get started with Svelte by creating our first small widget.

Our widget will be a filter list component like that you see on web applications like Slack with its channel chooser.

We will start writing our HTML code in the App.html section of the Svelte REPL. As we go along you will notice I will define some classes on each HTML element for styling the component later on.

The elements we will need for this widget is an input field for us to type our value into:

<div class="filtering-list">
  <div class="filter-search">
    <input type="text" class="search">
  </div>
</div>

Now that we have our input field, we can start adding some Svelte specific properties, in order to make the value entered dynamic and available later on in our app. For this we will add the bind:value property with a value of q.

<input bind:value="q" type="text" class="search">

For a quick test to see how this works, lets add this bit of code below the filter-search closing div tag.

<div class="filtering-list">
  <div class="filter-search">
    <input bind:value="q" type="text" class="search">
  </div>
  {{q}}
</div>

You may notice a side-effect of using a value in bind:value that is not defined, by default the value q is undefined and such will be outputted on the screen. Assign q to an empty string over in the panel on the bottom right where it says name in the REPL.

Now as you type into the input field, you should see the value getting printed out below as you type.

So now we need a list for the input value to filter through.

<div class="filtering-list">
  <div class="filter-search">
    <input bind:value="q" type="text" class="search">
  </div>

  <ul class="filter-list">
    {{#each list as name}}
      <li>#{{name}}</li>
    {{/each}}
  </ul>
</div>

Same as earlier, also assign list to an empty array over in the panel on the bottom right in the REPL. Otherwise this will throw an error in the REPL.

With this now in place, we have most of our user interface setup and ready to receive values. But you may have noticed that there is currently no association between the bind:value of q and the list. This is where we will start writing actual Javascript code.

One of the nice things about Svelte components is that you write all your HTML, CSS and Javascript code in the same file or in this instance in the same column in the REPL.

The first piece of code we need is to export the object we will write out Svelte related Javascript code in.

<script>
  export default {
  }
</script>

You might have noticed the script tag and be wondering, why are we writing our Javascript inline again, I thought that was a bad thing? well luckily in the case of Svelte, this is not a bad thing as our component once completed will be loaded as an external file in our actual final product.

Earlier we defined the q and the list in the bottom right column of the REPL, but I would normally move this into this part of our code to give the widget a default state if its loaded with no values assigned.

<script>
  export default {
    data() {
      return {
        q: '',
        list: []
      }
    }
  }
</script>

Change the value of list in the panel on the bottom right to something like [``"``angular``"``, "``backbone``"``, "ember", "glimmer", "react", "svelte", "vue"]

Now that we have our initial state for our application, we can go ahead and add code for the filtering to work as expected. To carry out this task we will use Svelte’s computed properties.

<script>
  export default {
    data() {
      return {
        q: '',
        list: []
      }
    },
    computed: {
      filteredList(q, list) {
        return q && q.length 
          ? list.filter(item => item.toLowerCase().indexOf(q.toLowerCase()) != -1) : list;
      }
    }
  }
</script>

We named our computed property filteredList and it is keeping watch of our two initial values, whenever one of these value’s change, our computed property will run. Now even with this we still won’t see any changes as we type a value into the field.

We can now go back to our template from earlier and change {{#each list as name}} to {{#each filteredList as name}}. Our complete code should now look like below.

<div class="filtering-list">
  <div class="filter-search">
    <input bind:value="q" type="text" class="search">
  </div>

  <ul class="filter-list">
    {{#each filteredList as name}}
      <li>#{{name}}</li>
    {{/each}}
  </ul>
</div>

<script>
  export default {
    data() {
      return {
        q: '',
        list: []
      }
    },
    computed: {
      filteredList(q, list) {
        return q && q.length 
          ? list.filter(item => item.toLowerCase().indexOf(q.toLowerCase()) != -1) : list;
      }
    }
  }
</script>

We now have a working application doing what we had set out for it to do in the beginning. We can improve this further by styling it to look better and do some code refactoring. Here is a link to the final widget with some CSS applied and the filter code refactored.

https://svelte.technology/repl?version=1.27.0&gist=d6909f77da67d9db0f2825992d036ec2

One of the questions some people might ask is, why use Svelte over any of the others available on the market, well with Svelte you can create Universal widgets that are not tied to any Javascript framework, since the end result from Svelte is plain old Javascript and no runtime library (this is subjective since the runtime library is minimal and part of the actual output code) is necessary to run it, you can drop it into any other projects you have.

I hope you enjoyed your first experience with Svelte and will continue your journey from here on out.