Logic

Since HTML can’t express logic such as conditionals and loops you would have to write something like this using JavaScript.

Example.htmlCopy

<div id="app"></div>

<script>
  let appElement = document.querySelector('#app')

  let user = {
	  loggedIn: false
	}

	function toggle() {
	  user.loggedIn = !user.loggedIn
		updateUI()
	}

	function updateUI() {
    let html

	  if (user.loggedIn) {
		  html = `<button>Log out</button>`
		}

		if (!user.loggedIn) {
		  html = `<button>Log in</button>`
		}

	  appElement.innerHTML = html
    appElement.querySelector('button').onclick = toggle
	}

  updateUI()
</script>

It doesn’t look bad but I think we can do better. This is the same example using an #if block in Svelte.

App.svelteCopy

<script>
	let user = {
		loggedIn: false
	}

	function toggle() {
		user.loggedIn = !user.loggedIn
	}
</script>

{#if user.loggedIn}
  <button on:click={toggle}>Log out</button>
{/if}

{#if !user.loggedIn}
  <button on:click={toggle}>Log in</button>
{/if}

Awesome, right? I want to emphasize how close Svelte is to HTML and I hope you’re excited about it.

There’s more logic blocks like #if#each#await, and #key for you to play around with.

This is using JavaScript to loop over a list of items and render them.

Example.htmlCopy

<div id="app"></div>

<script>
  let appElement = document.querySelector('#app')

	let todos = [
		{ id: 1, text: 'Todo 1', completed: true },
		{ id: 2, text: 'Todo 2', completed: false },
		{ id: 3, text: 'Todo 3', completed: false },
		{ id: 4, text: 'Todo 4', completed: false },
	]

	let todosHtml = ''

	for (let todo of todos) {
    let checked = todo.completed ? 'checked' : null

	  todosHtml += `
      <li data-id=${todo.id}>
		    <input ${checked} type="checkbox" />
		    <span>${todo.text}</span>
	    </li>
		`
	}

	appElement.innerHTML = `<ul>${todosHtml}</ul>`
</script>

The same example using #each in Svelte.

App.svelteCopy

<script>
	let todos = [
		{ id: 1, text: 'Todo 1', completed: true },
		{ id: 2, text: 'Todo 2', completed: false },
		{ id: 3, text: 'Todo 3', completed: false },
		{ id: 4, text: 'Todo 4', completed: false },
	]
</script>

<ul>
{#each todos as todo}
  <li>
		<input checked={todo.completed} type="checkbox" />
		<span>{todo.text}</span>
	</li>
{/each}
</ul>

You can destructure values from the item you’re iterating over, get the index, and provide a key so Svelte can keep track of changes. Avoid using the index as the key because it’s not guaranteed to be unique so use a unique value instead.

App.svelteCopy

<ul>
{#each todos as {id, text, completed}, index (id)}
  <li>
		<input checked={completed} type="checkbox" />
		<span>{text}</span>
	</li>
{/each}
</ul>

If you’re fetching data on the client this is how it would look using JavaScript.

Example.htmlCopy

<div id="app"></div>

<script>
  let appElement = document.querySelector('#app')

  async function fetchPokemon(pokemonName) {
    let url = `https://pokeapi.co/api/v2/pokemon/`
    let response = await fetch(`${url}${pokemonName}`)
    let { name, sprites } = await response.json()

    return {
      name,
      image: sprites['front_default']
    }
  }

  async function renderUI() {
    let { name, image } = await fetchPokemon('pikachu')

    appElement.innerHTML = `
      <h1>${name}</h1>
      <img src=${image} alt=${name} />
    `
  }

  renderUI()
</script>

In Svelte you can easily resolve a promise using the #await block but you can also resolve the promise in the <script> tag if you want .

App.svelteCopy

<script>
  async function fetchPokemon(pokemonName) {
    let url = `https://pokeapi.co/api/v2/pokemon/`
    let response = await fetch(`${url}${pokemonName}`)
    let { name, sprites } = await response.json()

		 return {
      name,
      image: sprites['front_default']
    }
  }
</script>

{#await fetchPokemon('pikachu')}
	<p>Fetching Pokemon...</p>
{:then pokemon}
	<h1>{pokemon.name}</h1>
	<img src={pokemon.image} alt={pokemon.name} />
{:catch error}
	<p>Something went wrong: {error.message}</p>
{/await}

In the JavaScript example we didn’t even add checks for scenarios where the promise could be pending, fulfilled, or rejected and just hope it works. 😬 Using Svelte you don’t have to think about it.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *