Svelte.js 3 Data & One-way Databinding Tutorial
In this Svelte tutorial we learn how to communicate between the View (markup) and the Logic (script).
We cover string interpolation, attribute binding and dynamic CSS class binding.
Lesson Video
If you prefer to learn visually, you can watch this lesson in video format.
Lesson Project
If you want to follow along with the examples in this lesson, you’ll need a Svelte app that was cloned with degit or scaffolded with Vite
If you already have an app from previous lessons, you can use that instead.
Script data in Svelte
Svelte allows us to use any data container that Javascript supports like variables, arrays, objects etc. The only requirement is that we define that data in the Logic (script section) of the component.
As an example, remove everthing from the root App component and then define a script section with a name constant.
<script>
const name = 'John'
</script>
Now that we have some data, we can do things with it, like binding it to the View (markup section).
What is Databinding?
Databinding is how we communicate between the View (markup) and the Logic (script) of the component.
There are several types of databinding in Svelte.
- One-way databinding from the Logic to the View. Data from the Logic is output in the View with String Interpolation or Attribute binding.
- One-way databinding from the View to the Logic. We react to events from the View, like a button click, with Event binding.
- Two-way databinding between the Logic and the View. Combining the two above, we can react to events and output something at the same time.
How to output (bind) data in Svelte with String Interpolation
If we hardcode our data into the HTML of our markup, we’ll always need to manually update it whenever the data changes. What we want instead is to update the data in a single place (the Logic) and have Svelte take care of updating the HTML for us.
This is very easy to do with a process called String Interpolation. We reference a piece of data in the markup and Svelte will replace the reference with the actual data.
To reference a data property, we wrap it in a pair of open-and-close curly braces (known as moustache syntax).
{ data }
As an example, let’s output the name constant we defined earlier in a heading in the root App component.
tip Remember that the markup section doesn’t require any specific wrapping element, it only needs to be outside of the <script> and <style> blocks.
<script>
const name = 'John'
</script>
<h1>Hello, { name }</h1>
If we run the example in the browser, we should see the greeting with the custom name we provided.
How to output (bind) HTML content in Svelte
When we bind data with string interpolation, that data is inserted as plain text because Svelte converts any special characters into their web-safe variants to help protect agains security concerns, like cross-site scripting.
Sometimes though, we may need to render raw HTML.
To demonstrate, let’s add a pair of <em> tags around the name in our example.
<script>
const name = '<em>John</em>'
</script>
<h1>Hello, { name }</h1>
If we save the file and take a look in the browser, the name will be displayed with the HTML characters instead of being emphasized.
Hello, <em>John</em>
We need to tell Svelte that we want to output the raw HTML by adding @html as a prefix to the string interpolation.
{@html data }
To demonstrate, let’s add it to the heading in our example.
<script>
const name = '<em>John</em>'
</script>
<h1>Hello, {@html name }</h1>
This time when we look in the browser, the name will be emphasized.
How to bind to HTML attributes in Svelte
Svelte allows us to bind values to any attribute of an HTML element.
Attribute binding also uses moustache syntax, but as the value of an attribute.
<element attribute="{ data }">
We are allowed to omit the double quotes.
<element attribute={ data }>
To demonstrate, let’s define a constant called headingId in the script section of our root App component example.
Then we’ll add the id attribute to the heading and bind the constant to it with moustache syntax.
<script>
const headingId = 'greeting'
</script>
<h1 id={headingId}>Hello</h1>
If we go back to the browser and inspect the heading element with the developer tools, we’ll see the id attribute is “greeting”.
<body>
<h1 id="greeting">Hello</h1>
</body>
The shorthand for Attribute Binding in Svelte
Because attribute binding is so common, Svelte allows us to use a shorthand.
If the attribute name is the same as the name of the data we’re binding, we can omit the attribute and only use the moustache syntax.
<!-- This -->
<element attribute={ attribute }>
<!-- Becomes -->
<element { attribute }>
To demonstrate, let’s change our example’s headingId value to just id in the script section and remove the attribute from the heading in the markup.
<script>
const id = 'greeting'
</script>
<h1 {id}>Hello</h1>
If we go back to the browser and inspect the heading in the browser’s developer tools, it still shows the id attribute as “greeting” like we expect.
Dynamic CSS classes in Svelte
Because styling is such a big part of an application, it’s worth it to dedicate a section to learning how to bind CSS classes, as well as binding them conditionally.
It’s especially useful if your styling is utility-based, or you use a utility-based framework like TailwindCSS.
Dynamic classes work the same as normal attribute binding, but the data we reference contains the name of the class we want to add.
<script>
const data = 'class-name'
</script>
<element class={ data }>
<style>
.class-name { }
</style>
As an example, let’s say we want to show the user a valid/invalid message when they enter something into an input field. But we want the valid text color to be green, and the invalid text color to be red.
We’ll start by adding a style block and defining two color classes with green and red. Then we’ll define a new constant in the script block called status , with one of the class names as its value.
Finally, we’ll bind the new constant to the class attribute on a paragraph element in the markup.
<script>
const status = 'valid'
</script>
<p class={status}>
Hello there
</p>
<style>
.valid { color: forestgreen }
.invalid { color: crimson }
</style>
If we take a look in the browser, the text in the paragraph will be green. That’s because we specified the valid (green color) class as the value for the constant.
If we change the constant to have the invalid (red color) class as its value, Svelte will change the class binding on the paragraph and the text will be red.
How to conditionally bind a CSS class in Svelte
You will often need to bind certain classes based on the results of a conditional evaluation. For example, you may want to change the color of an input when its value is invalid.
Svelte allows basic Javascript expressions in its attribute bindings, so we can use the Javascript ternary expression to conditionally check which class to add.
<element class={condition ? 'true_class' : 'false_class'} />
note Class names must be wrapped in quotes, otherwise Svelte will not add them.
To demonstrate, let’s define a boolean constant called isValid in our example. Then in our class binding we’ll use a ternary to add the classes based on isValid ’s value.
<script>
const isValid = false
</script>
<p class={isValid ? 'valid' : 'invalid'}>
Hello there
</p>
<style>
.valid { color: forestgreen }
.invalid { color: crimson }
</style>
Because isValid is false, Svelte will use the invalid class and the text in the browser will show as red. If we change isValid to true, Svelte will use the valid class and the text will be green.
An alternative syntax for Conditional Binding
Because the conditional class binding pattern is so common, Svelte provides us with a specialized directive that allows us to toggle a class based on a condition.
tip A directive is a custom attribute that controls the element’s behavior in some way.
To use the directive, we write the class attribute, followed by a : (colon) and the class name that we want to apply if a condition proves true. As its value, we specify the condition in moustache syntax.
<element class:class_name={condition}>
To demonstrate, let’s convert our example to use valid as the class name and isValid as the condition.
<script>
const isValid = true
</script>
<p class:valid={isValid}>
Hello there
</p>
<style>
.valid { color: forestgreen }
.invalid { color: crimson }
</style>
If we take a look in the browser, the text shows green.
But what about when isValid is false?
In that case, we simply add another class toggle directive with invalid as the class name and !isValid as the condition.
<script>
const isValid = false
</script>
<p
class:valid={isValid}
class:invalid={!isValid}
>
Hello there
</p>
<style>
.valid { color: forestgreen }
.invalid { color: crimson }
</style>
This time, the text will show red because isValid is false.