Vue conditional rendering: editing existing todos - Learn web development

Vue conditional rendering: editing existing todos
=================================================

* Previous
* Overview: Client-side JavaScript frameworks
* Next

Now it is time to add one of the major parts of functionality that we're still missing — the ability to edit existing todo items. To do this, we will take advantage of Vue's conditional rendering capabilities — namely `v-if` and `v-else` — to allow us to toggle between the existing todo item view, and an edit view where you can update todo item labels. We'll also look at adding functionality to delete todo items.

|  |  |
| --- | --- |
| Prerequisites: |
 Familiarity with the core HTML,
 CSS, and
 JavaScript languages,
 knowledge of the
 terminal/command line.

 Vue components are written as a combination of JavaScript objects that
 manage the app's data and an HTML-based template syntax that maps to
 the underlying DOM structure. For installation, and to use some of the
 more advanced features of Vue (like Single File Components or render
 functions), you'll need a terminal with node + npm installed.
  |
| Objective: | To learn how to do conditional rendering in Vue. |

Creating an editing component
-----------------------------

We can start by creating a separate component to handle the editing functionality. In your `components` directory, create a new file called `ToDoItemEditForm.vue`. Copy the following code into that file:

```html
<template>
  <form class="stack-small" @submit.prevent="onSubmit">
    <div>
      <label class="edit-label">Edit Name for "{{label}}"</label>
      <input
 :id="id"
 type="text"
 autocomplete="off"
 v-model.lazy.trim="newLabel" />
    </div>
    <div class="btn-group">
      <button type="button" class="btn" @click="onCancel">
        Cancel
        <span class="visually-hidden">editing {{label}}</span>
      </button>
      <button type="submit" class="btn btn\_\_primary">
        Save
        <span class="visually-hidden">edit for {{label}}</span>
      </button>
    </div>
  </form>
</template>
<script>
 export default {
 props: {
 label: {
 type: String,
 required: true,
 },
 id: {
 type: String,
 required: true,
 },
 },
 data() {
 return {
 newLabel: this.label,
 };
 },
 methods: {
 onSubmit() {
 if (this.newLabel && this.newLabel !== this.label) {
 this.$emit("item-edited", this.newLabel);
 }
 },
 onCancel() {
 this.$emit("edit-cancelled");
 },
 },
 };
</script>
<style scoped>
 .edit-label {
 font-family: Arial, sans-serif;
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale;
 color: #0b0c0c;
 display: block;
 margin-bottom: 5px;
 }
 input {
 display: inline-block;
 margin-top: 0.4rem;
 width: 100%;
 min-height: 4.4rem;
 padding: 0.4rem 0.8rem;
 border: 2px solid #565656;
 }
 form {
 display: flex;
 flex-direction: row;
 flex-wrap: wrap;
 }
 form > \* {
 flex: 0 0 100%;
 }
</style>
```

**Note:** Walk through the above code then read the below description to make sure you understand everything the component is doing before moving on. This is a useful way to help reinforce everything you've learned so far.

This code sets up the core of the edit functionality. We create a form with an `<input>` field for editing the name of our to-do.

There is a "Save" button and a "Cancel" button:

* When the "Save" button is clicked, the component emits the new label via an `item-edited` event.
* When the "Cancel" button is clicked, the component signals this by emitting an `edit-cancelled` event.
Modifying our ToDoItem component
--------------------------------

Before we can add `ToDoItemEditForm` to our app, we need to make a few modifications to our `ToDoItem` component. Specifically, we need to add a variable to track if the item is being edited, and a button to toggle that variable. We'll also add a `Delete` button since deletion is closely related.

Update your `ToDoItem`'s template as shown below.

```html
<template>
  <div class="stack-small">
    <div class="custom-checkbox">
      <input
 type="checkbox"
 class="checkbox"
 :id="id"
 :checked="isDone"
 @change="$emit('checkbox-changed')" />
      <label :for="id" class="checkbox-label">{{label}}</label>
    </div>
    <div class="btn-group">
      <button type="button" class="btn" @click="toggleToItemEditForm">
        Edit <span class="visually-hidden">{{label}}</span>
      </button>
      <button type="button" class="btn btn\_\_danger" @click="deleteToDo">
        Delete <span class="visually-hidden">{{label}}</span>
      </button>
    </div>
  </div>
</template>
```

We've added a wrapper `<div>` around the whole template for layout purposes.

We've also added "Edit" and "Delete" buttons:

* The "Edit" button, when clicked, will toggle displaying the `ToDoItemEditForm` component so we can use it to edit our todo item, via an event handler function called `toggleToItemEditForm()`. This handler will set an `isEditing` flag to true. To do that, we'll need to first define it inside our `data()` property.
* The "Delete" button, when clicked, will delete the todo item via an event handler function called `deleteToDo()`. In this handler we'll emit an `item-deleted` event to our parent component so the list can be updated.

Let's define our click handlers, and the necessary `isEditing` flag.

Add `isEditing` below your existing `isDone` data point:

```js
data() {
  return {
    isDone: this.done,
    isEditing: false
  };
}
```

Now add your methods inside a methods property, right below your `data()` property:

```js
methods: {
    deleteToDo() {
      this.$emit('item-deleted');
    },
    toggleToItemEditForm() {
      this.isEditing = true;
    }
  }
```

Conditionally displaying components via v-if and v-else
-------------------------------------------------------

Now we have an `isEditing` flag that we can use to signify that the item is being edited (or not). If `isEditing` is true, we want to use that flag to display our `ToDoItemEditForm` instead of the checkbox. To do that, we'll use another Vue directive: `v-if`.

The `v-if` directive will only render a block if the value passed to it is truthy. This is similar to how an `if` statement works in JavaScript. `v-if` also has corresponding `v-else-if` and `v-else` directives to provide the equivalent of JavaScript `else if` and `else` logic inside Vue templates.

It's important to note that `v-else` and `v-else-if` blocks need to be the first sibling of a `v-if`/`v-else-if` block, otherwise Vue will not recognize them. You can also attach `v-if` to a `<template>` tag if you need to conditionally render an entire template.

Lastly, you can use a `v-if` + `v-else` at the root of your component to display only one block or another, since Vue will only render one of these blocks at a time. We'll do this in our app, as it will allow us to replace the code that displays our to-do item with the edit form.

First of all add `v-if="!isEditing"` to the root `<div>` in your `ToDoItem` component,

```html
<div class="stack-small" v-if="!isEditing"></div>
```

Next, below that `<div>`'s closing tag add the following line:

```html
<to-do-item-edit-form v-else :id="id" :label="label"></to-do-item-edit-form>
```

We also need to import and register the `ToDoItemEditForm` component, so we can use it inside this template. Add this line at the top of your `<script>` element:

```js
import ToDoItemEditForm from "./ToDoItemEditForm";
```

And add a `components` property above the `props` property inside the component object:

```js
components: {
  ToDoItemEditForm
},
```

Now, if you go to your app and click a todo item's "Edit" button, you should see the checkbox replaced with the edit form.

![The todo list app, with Edit and Delete buttons shown, and one of the todos in edit mode, with an edit input and save and cancel buttons shown](/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_conditional_rendering/todo-edit-delete.png)

However, there's currently no way to go back. To fix that, we need to add some more event handlers to our component.

Getting back out of edit mode
-----------------------------

First, we need to add an `itemEdited()` method to our `ToDoItem` component's `methods`. This method should take the new item label as an argument, emit an `itemEdited` event to the parent component, and set `isEditing` to `false`.

Add it now, below your existing methods:

```js
itemEdited(newLabel) {
  this.$emit('item-edited', newLabel);
  this.isEditing = false;
}
```

Next, we'll need an `editCancelled()` method. This method will take no arguments and just serve to set `isEditing` back to `false`. Add this method below the previous one:

```js
editCancelled() {
  this.isEditing = false;
}
```

Last for this section, we'll add event handlers for the events emitted by the `ToDoItemEditForm` component, and attach the appropriate methods to each event.

Update your `<to-do-item-edit-form></to-do-item-edit-form>` call to look like so:

```html
<to-do-item-edit-form
 v-else
 :id="id"
 :label="label"
 @item-edited="itemEdited"
 @edit-cancelled="editCancelled">
</to-do-item-edit-form>
```

Updating and deleting todo items
--------------------------------

Now we can toggle between the edit form and the checkbox. However, we haven't actually handled updating the `ToDoItems` array back in `App.vue`. To fix that, we need to listen for the `item-edited` event, and update the list accordingly. We'll also want to handle the delete event so that we can delete todo items.

Add the following new methods to your `App.vue`'s component object, below the existing methods inside the `methods` property:

```js
deleteToDo(toDoId) {
  const itemIndex = this.ToDoItems.findIndex((item) => item.id === toDoId);
  this.ToDoItems.splice(itemIndex, 1);
},
editToDo(toDoId, newLabel) {
  const toDoToEdit = this.ToDoItems.find((item) => item.id === toDoId);
  toDoToEdit.label = newLabel;
}
```

Next, we'll add the event listeners for the `item-deleted` and `item-edited` events:

* For `item-deleted`, you'll need to pass the `item.id` to the method.
* For `item-edited`, you'll need to pass the `item.id` and the special `$event` variable. This is a special Vue variable used to pass event data to methods. When using native HTML events (like `click`), this will pass the native event object to your method.

Update the `<to-do-item></to-do-item>` call inside the `App.vue` template to look like this:

```html
<to-do-item
 :label="item.label"
 :done="item.done"
 :id="item.id"
 @checkbox-changed="updateDoneStatus(item.id)"
 @item-deleted="deleteToDo(item.id)"
 @item-edited="editToDo(item.id, $event)">
</to-do-item>
```

And there you have it — you should now be able to edit and delete items from the list!

Fixing a small bug with isDone status
-------------------------------------

This is great so far, but we've actually introduced a bug by adding in the edit functionality. Try doing this:

1. Check (or uncheck) one of the todo checkboxes.
2. Press the "Edit" button for that todo item.
3. Cancel the edit by pressing the "Cancel" button.

Note the state of the checkbox after you cancel — not only has the app forgotten the state of the checkbox, but the done status of that todo item is now out of whack. If you try checking (or unchecking) it again, the completed count will change in the opposite way to what you'd expect. This is because the `isDone` inside `data` is only given the value `this.done` on component load.

Fixing this is fortunately quite easy — we can do this by converting our `isDone` data item into a computed property — another advantage of computed properties is that they preserve reactivity, meaning (among other things) that their state is saved when the template changes like ours is now doing.

So, let's implement the fix in `ToDoItem.vue`:

1. Remove the following line from inside our `data()` property:

```js
isDone: this.done,
```

2. Add the following block below the data() { } block:

```js
computed: {
  isDone() {
    return this.done;
  }
},
```

Now when you save and reload, you'll find that the problem is solved — the checkbox state is now preserved when you switch between todo item templates.

Understanding the tangle of events
----------------------------------

One of the most potentially confusing parts is the tangle of standard and custom events we've used to trigger all the interactivity in our app. To understand this better, it is a good idea to write out a flow chart, description, or diagram of what events are emitted where, where they are being listened for, and what happens as a result of them firing.

### App.vue

`<to-do-form>` listens for:

* `todo-added` event emitted by the `onSubmit()` method inside the `ToDoForm` component when the form is submitted.
 **Result**: `addToDo()` method invoked to add new todo item to the `ToDoItems` array.

`<to-do-item>` listens for:

* `checkbox-changed` event emitted by the checkbox `<input>` inside the `ToDoItem` component when it is checked or unchecked.
 **Result**: `updateDoneStatus()` method invoked to update done status of associated todo item.
* `item-deleted` event emitted by the `deleteToDo()` method inside the `ToDoItem` component when the "Delete" button is pressed.
 **Result**: `deleteToDo()` method invoked to delete associated todo item.
* `item-edited` event emitted by the `itemEdited()` method inside the `ToDoItem` component when the `item-edited` event emitted by the `onSubmit()` method inside the `ToDoItemEditForm` has been successfully listened for. Yes, this is a chain of two different `item-edited` events!
 **Result**: `editToDo()` method invoked to update label of associated todo item.
### ToDoForm.vue

`<form>` listens for `submit` event.
 **Result**: `onSubmit()` method is invoked, which checks that the new label is not empty, then emits the `todo-added` event (which is then listened for inside `App.vue`, see above), and finally clears the new label `<input>`.

### ToDoItem.vue

 The `<input>` of `type="checkbox"` listens for `change` events.
 **Result**: `checkbox-changed` event emitted when the checkbox is checked/unchecked (which is then listened for inside `App.vue`; see above).

 "Edit" `<button>` listens for `click` event.
 **Result**: `toggleToItemEditForm()` method is invoked, which toggles `this.isEditing` to `true`, which in turn displays the todo item's edit form on re-render.

 "Delete" `<button>` listens for `click` event.
 **Result**: `deleteToDo()` method is invoked, which emits the `item-deleted` event (which is then listened for inside `App.vue`; see above).

`<to-do-item-edit-form>` listens for:

* `item-edited` event emitted by the `onSubmit()` method inside the `ToDoItemEditForm` component when the form is successfully submitted.
 **Result**: `itemEdited()` method is invoked, which emits the `item-edited` event (which is then listened for inside `App.vue`, see above), and sets `this.isEditing` back to `false`, so that the edit form is no longer shown on re-render.
* `edit-cancelled` event emitted by the `onCancel()` method inside the `ToDoItemEditForm` component when the "Cancel" button is clicked.
 **Result**: `editCancelled()` method is invoked, which sets `this.isEditing` back to `false`, so that the edit form is no longer shown on re-render.
### ToDoItemEditForm.vue

`<form>` listens for `submit` event.
 **Result**: `onSubmit()` method is invoked, which checks to see if the new label value is not blank, and not the same as the old one, and if so emits the `item-edited` event (which is then listened for inside `ToDoItem.vue`, see above).

 "Cancel" `<button>` listens for `click` event.
 **Result**: `onCancel()` method is invoked, which emits the `edit-cancelled` event (which is then listened for inside `ToDoItem.vue`, see above).

Summary
-------

This article has been fairly intense, and we covered a lot here. We've now got edit and delete functionality in our app, which is fairly exciting. We are nearing the end of our Vue series now. The last bit of functionality to look at is focus management, or put another way, how we can improve our app's keyboard accessibility.

* Previous
* Overview: Client-side JavaScript frameworks
* Next


Componentizing our Svelte app - Learn web development

Componentizing our Svelte app
=============================

* Previous
* Overview: Client-side JavaScript frameworks
* Next

In the last article we started developing our to-do list app. The central objective of this article is to look at how to break our app into manageable components and share information between them. We'll componentize our app, then add more functionality to allow users to update existing components.

|  |  |
| --- | --- |
| Prerequisites: |
 At minimum, it is recommended that you are familiar with the core
 HTML,
 CSS, and
 JavaScript languages, and
 have knowledge of the
 terminal/command line.

 You'll need a terminal with node and npm installed to compile and build
 your app.
  |
| Objective: |
 To learn how to break our app into components and share information
 among them.
  |

Code along with us
------------------

### Git

Clone the GitHub repo (if you haven't already done it) with:

```bash
git clone https://github.com/opensas/mdn-svelte-tutorial.git
```

Then to get to the current app state, run

```bash
cd mdn-svelte-tutorial/04-componentizing-our-app
```

Or directly download the folder's content:

```bash
npx degit opensas/mdn-svelte-tutorial/04-componentizing-our-app
```

Remember to run `npm install && npm run dev` to start your app in development mode.

### REPL

To code along with us using the REPL, start at

https://svelte.dev/repl/99b9eb228b404a2f8c8959b22c0a40d3?version=3.23.2

Breaking the app into components
--------------------------------

In Svelte, an application is composed from one or more components. A component is a reusable, self-contained block of code that encapsulates HTML, CSS, and JavaScript that belong together, written into a `.svelte` file. Components can be big or small, but they are usually clearly defined: the most effective components serve a single, obvious purpose.

The benefits of defining components are comparable to the more general best practice of organizing your code into manageable pieces. It will help you understand how they relate to each other, it will promote reuse, and it will make your code easier to reason about, maintain, and extend.

But how do you know what should be split into its own component?

There are no hard rules for this. Some people prefer an intuitive approach and start looking at the markup and drawing boxes around every component and subcomponent that seems to have its own logic.

Other people apply the same techniques used for deciding if you should create a new function or object. One such technique is the single responsibility principle — that is, a component should ideally only do one thing. If it ends up growing, it should be split into smaller subcomponents.

Both approaches should complement each other, and help you decide how to better organize your components.

Eventually, we will split up our app into the following components:

* `Alert.svelte`: A general notification box for communicating actions that have occurred.
* `NewTodo.svelte`: The text input and button that allow you to enter a new to-do item.
* `FilterButton.svelte`: The *All*, *Active*, and *Completed* buttons that allow you to apply filters to the displayed to-do items.
* `TodosStatus.svelte`: The "x out of y items completed" heading.
* `Todo.svelte`: An individual to-do item. Each visible to-do item will be displayed in a separate copy of this component.
* `MoreActions.svelte`: The *Check All* and *Remove Completed* buttons at the bottom of the UI that allow you to perform mass actions on the to-do items.

![graphical representation of the list of components in our app](/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_components/01-todo-components.png)

In this article we will concentrate on creating the `FilterButton` and `Todo` components; we'll get to the others in future articles.

Let's get started.

**Note:** In the process of creating our first couple of components, we will also learn different techniques to communicate between components, and the pros and cons of each.

Extracting our filter component
-------------------------------

We'll begin by creating our `FilterButton.svelte`.

1. First of all, create a new file, `components/FilterButton.svelte`.
2. Inside this file we will declare a `filter` prop, and then copy the relevant markup over to it from `Todos.svelte`. Add the following content into the file:

```svelte
<script>
 export let filter = 'all'
</script>

<div class="filters btn-group stack-exception">
  <button class="btn toggle-btn" class:btn\_\_primary={filter === 'all'} aria-pressed={filter === 'all'} on:click={() => filter = 'all'} >
    <span class="visually-hidden">Show</span>
    <span>All</span>
    <span class="visually-hidden">tasks</span>
  </button>
  <button class="btn toggle-btn" class:btn\_\_primary={filter === 'active'} aria-pressed={filter === 'active'} on:click={() => filter = 'active'} >
    <span class="visually-hidden">Show</span>
    <span>Active</span>
    <span class="visually-hidden">tasks</span>
  </button>
  <button class="btn toggle-btn" class:btn\_\_primary={filter === 'completed'} aria-pressed={filter === 'completed'} on:click={() => filter = 'completed'} >
    <span class="visually-hidden">Show</span>
    <span>Completed</span>
    <span class="visually-hidden">tasks</span>
  </button>
</div>
```

3. Back in our `Todos.svelte` component, we want to make use of our `FilterButton` component. First of all, we need to import it. Add the following line at the top of the `Todos.svelte <script>` section:

```js
import FilterButton from "./FilterButton.svelte";
```

4. Now replace the `<div class="filters...` element with a call to the `FilterButton` component, which takes the current filter as a prop. The below line is all you need:

```svelte
<FilterButton {filter} />
```

**Note:** Remember that when the HTML attribute name and variable match, they can be replaced with `{variable}`. That's why we could replace `<FilterButton filter={filter} />` with `<FilterButton {filter} />`.

So far so good! Let's try out the app now. You'll notice that when you click on the filter buttons, they are selected and the style updates appropriately. But we have a problem: the to-dos aren't filtered. That's because the `filter` variable flows down from the `Todos` component to the `FilterButton` component through the prop, but changes occurring in the `FilterButton` component don't flow back up to its parent — the data binding is one-way by default. Let's look at a way to solve this.

Sharing data between components: passing a handler as a prop
------------------------------------------------------------

One way to let child components notify their parents of any changes is to pass a handler as a prop. The child component will execute the handler, passing the needed information as a parameter, and the handler will modify the parent's state.

In our case, the `FilterButton` component will receive an `onclick` handler from its parent. Whenever the user clicks on any filter button, the child will call the `onclick` handler, passing the selected filter as a parameter back up to its parent.

We will just declare the `onclick` prop assigning a dummy handler to prevent errors, like this:

```js
export let onclick = (clicked) => {};
```

And we'll declare the reactive statement `$: onclick(filter)` to call the `onclick` handler whenever the `filter` variable is updated.

1. The `<script>` section of our `FilterButton` component should end up looking like this. Update it now:

```js
export let filter = "all";
export let onclick = (clicked) => {};
$: onclick(filter);
```

2. Now when we call `FilterButton` inside `Todos.svelte`, we'll need to specify the handler. Update it like this:

```svelte
<FilterButton {filter} onclick={ (clicked) => filter = clicked }/>
```

When any filter button is clicked, we just update the filter variable with the new filter. Now our `FilterButton` component will work again.

Easier two-way data binding with the bind directive
---------------------------------------------------

In the previous example we realized that our `FilterButton` component wasn't working because our application state was flowing down from parent to child through the `filter` prop, but it wasn't going back up. So we added an `onclick` prop to let the child component communicate the new `filter` value to its parent.

It works OK, but Svelte provides us with an easier and more straightforward way to achieve two-way data binding. Data ordinarily flows down from parent to child using props. If we want it to also flow the other way, from child to parent, we can use the `bind:` directive.

Using `bind`, we will tell Svelte that any changes made to the `filter` prop in the `FilterButton` component should propagate back up to the parent component, `Todos`. That is, we will bind the `filter` variable's value in the parent to its value in the child.

1. In `Todos.svelte`, update the call to the `FilterButton` component as follows:

```svelte
<FilterButton bind:filter={filter} />
```

As usual, Svelte provides us with a nice shorthand: `bind:value={value}` is equivalent to `bind:value`. So in the above example you could just write `<FilterButton bind:filter />`.
2. The child component can now modify the value of the parent's filter variable, so we no longer need the `onclick` prop. Modify the `<script>` element of your `FilterButton` like this:

```svelte
<script>
 export let filter = "all";
</script>
```

3. Try your app again, and you should still see your filters working correctly.
Creating our Todo component
---------------------------

Now we will create a `Todo` component to encapsulate each individual to-do, including the checkbox and some editing logic so you can change an existing to-do.

Our `Todo` component will receive a single `todo` object as a prop. Let's declare the `todo` prop and move the code from the `Todos` component. Just for now, we'll replace the call to `removeTodo` with an alert. We'll add that functionality back in later on.

1. Create a new component file, `components/Todo.svelte`.
2. Put the following contents inside this file:

```svelte
<script>
 export let todo
</script>

<div class="stack-small">
  <div class="c-cb">
    <input type="checkbox" id="todo-{todo.id}"
 on:click={() => todo.completed = !todo.completed}
 checked={todo.completed}
 />
    <label for="todo-{todo.id}" class="todo-label">{todo.name}</label>
  </div>
  <div class="btn-group">
    <button type="button" class="btn">
      Edit <span class="visually-hidden">{todo.name}</span>
    </button>
    <button type="button" class="btn btn\_\_danger" on:click={() => alert('not implemented')}>
      Delete <span class="visually-hidden">{todo.name}</span>
    </button>
  </div>
</div>
```

3. Now we need to import our `Todo` component into `Todos.svelte`. Go to this file now, and add the following `import` statement below your previous one:

```js
import Todo from "./Todo.svelte";
```

4. Next we need to update our `{#each}` block to include a `<Todo>` component for each to-do, rather than the code that has been moved out to `Todo.svelte`. We are also passing the current `todo` object into the component as a prop.
 Update the `{#each}` block inside `Todos.svelte` like so:

```svelte
<ul role="list" class="todo-list stack-large" aria-labelledby="list-heading">
  {#each filterTodos(filter, todos) as todo (todo.id)}
  <li class="todo">
    <Todo {todo} />
  </li>
  {:else}
  <li>Nothing to do here!</li>
  {/each}
</ul>
```

The list of to-dos is displayed on the page, and the checkboxes should work (try checking/unchecking a couple, and then observing that the filters still work as expected), but our "x out of y items completed" status heading will no longer update accordingly. That's because our `Todo` component is receiving the to-do via the prop, but it's not sending any information back to its parent. We'll fix this later on.

Sharing data between components: props-down, events-up pattern
--------------------------------------------------------------

The `bind` directive is pretty straightforward and allows you to share data between a parent and child component with minimal fuss. However, when your application grows larger and more complex, it can easily get difficult to keep track of all your bound values. A different approach is the "props-down, events-up" communication pattern.

Basically, this pattern relies on child components receiving data from their parents via props and parent components updating their state by handling events emitted from child components. So props *flow down* from parent to child and events *bubble up* from child to parent. This pattern establishes a two-way flow of information, which is predictable and easier to reason about.

Let's look at how to emit our own events to re-implement the missing *Delete* button functionality.

To create custom events, we'll use the `createEventDispatcher` utility. This will return a `dispatch()` function that will allow us to emit custom events. When you dispatch an event, you have to pass the name of the event and, optionally, an object with additional information that you want to pass to every listener. This additional data will be available on the `detail` property of the event object.

**Note:** Custom events in Svelte share the same API as regular DOM events. Moreover, you can bubble up an event to your parent component by specifying `on:event` without any handler.

We'll edit our `Todo` component to emit a `remove` event, passing the to-do being removed as additional information.

1. First of all, add the following lines to the top of the `Todo` component's `<script>` section:

```js
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
```

2. Now update the *Delete* button in the markup section of the same file to look like so:

```svelte
<button type="button" class="btn btn\_\_danger" on:click={() => dispatch('remove', todo)}>
  Delete <span class="visually-hidden">{todo.name}</span>
</button>
```

With `dispatch('remove', todo)` we are emitting a `remove` event, and passing as additional data the `todo` being deleted. The handler will be called with an event object available, with the additional data available in the `event.detail` property.
3. Now we have to listen to that event from inside `Todos.svelte` and act accordingly. Go back to this file and update your `<Todo>` component call like so:

```svelte
<Todo {todo} on:remove={(e) => removeTodo(e.detail)} />
```

Our handler receives the `e` parameter (the event object), which as described before holds the to-do being deleted in the `detail` property.
4. At this point, if you try out your app again, you should see that the *Delete* functionality now works again. So our custom event has worked as we hoped. In addition, the `remove` event listener is sending the data change back up to the parent, so our "x out of y items completed" status heading will now update appropriately when to-dos are deleted.

Now we'll take care of the `update` event, so that our parent component can get notified of any modified to-do.

Updating to-dos
---------------

We still have to implement functionality to allow us to edit existing to-dos. We'll have to include an editing mode in the `Todo` component. When entering editing mode, we'll show an `<input>` field to allow us to edit the current to-do name, with two buttons to confirm or cancel our changes.

### Handling the events

1. We'll need one variable to track whether we are in editing mode and another to store the name of the task being updated. Add the following variable definitions at the bottom of the `<script>` section of the `Todo` component:

```js
let editing = false; // track editing mode
let name = todo.name; // hold the name of the to-do being edited
```

2. We have to decide what events our `Todo` component will emit:
    * We could emit different events for the status toggle and editing of the name (for example, `updateTodoStatus` and `updateTodoName`).
    * Or we could take a more generic approach and emit a single `update` event for both operations.We will take the second approach so that we can demonstrate a different technique. The advantage of this approach is that later we can add more fields to the to-dos and still handle all updates with the same event.
 Let's create an `update()` function that will receive the changes and will emit an update event with the modified to-do. Add the following, again to the bottom of the `<script>` section:

```js
function update(updatedTodo) {
  todo = { ...todo, ...updatedTodo }; // applies modifications to todo
  dispatch("update", todo); // emit update event
}
```

Here we are using the spread syntax to return the original to-do with the modifications applied to it.
3. Next we'll create different functions to handle each user action. When the to-do is in editing mode, the user can save or cancel the changes. When it's not in editing mode, the user can delete the to-do, edit it, or toggle its status between completed and active.
 Add the following set of functions below your previous function to handle these actions:

```js
function onCancel() {
  name = todo.name; // restores name to its initial value and
  editing = false; // and exit editing mode
}

function onSave() {
  update({ name }); // updates todo name
  editing = false; // and exit editing mode
}

function onRemove() {
  dispatch("remove", todo); // emit remove event
}

function onEdit() {
  editing = true; // enter editing mode
}

function onToggle() {
  update({ completed: !todo.completed }); // updates todo status
}
```

### Updating the markup

Now we need to update our `Todo` component's markup to call the above functions when the appropriate actions are taken.

To handle the editing mode, we are using the `editing` variable, which is a boolean. When it's `true`, it should display the `<input>` field for editing the to-do name, and the *Cancel* and *Save* buttons. When it's not in editing mode, it will display the checkbox, the to-do name, and the buttons to edit and delete the to-do.

To achieve this we will use an `if` block. The `if` block conditionally renders some markup. Take into account that it won't just show or hide the markup based on the condition — it will dynamically add and remove the elements from the DOM, depending on the condition.

When `editing` is `true`, for example, Svelte will show the update form; when it's `false`, it will remove it from the DOM and add in the checkbox. Thanks to Svelte reactivity, assigning the value of the editing variable will be enough to display the correct HTML elements.

The following gives you an idea of what the basic `if` block structure looks like:

```svelte
<div class="stack-small">
  {#if editing}
  <!-- markup for editing to-do: label, input text, Cancel and Save Button -->
  {:else}
  <!-- markup for displaying to-do: checkbox, label, Edit and Delete Button -->
  {/if}
</div>
```

The non-editing section — that is, the `{:else}` part (lower half) of the `if` block — will be very similar to the one we had in our `Todos` component. The only difference is that we are calling `onToggle()`, `onEdit()`, and `onRemove()`, depending on the user action.

```svelte
{:else}
  <div class="c-cb">
    <input type="checkbox" id="todo-{todo.id}"
 on:click={onToggle} checked={todo.completed}
 >
    <label for="todo-{todo.id}" class="todo-label">{todo.name}</label>
  </div>
  <div class="btn-group">
    <button type="button" class="btn" on:click={onEdit}>
      Edit<span class="visually-hidden"> {todo.name}</span>
    </button>
    <button type="button" class="btn btn\_\_danger" on:click={onRemove}>
      Delete<span class="visually-hidden"> {todo.name}</span>
    </button>
  </div>
{/if}
</div>
```

It is worth noting that:

* When the user presses the *Edit* button, we execute `onEdit()`, which just sets the `editing` variable to `true`.
* When the user clicks on the checkbox, we call the `onToggle()` function, which executes `update()`, passing an object with the new `completed` value as a parameter.
* The `update()` function emits the `update` event, passing as additional information a copy of the original to-do with the changes applied.
* Finally, the `onRemove()` function emits the `remove` event, passing the `todo` to be deleted as additional data.

The editing UI (the upper half) will contain an `<input>` field and two buttons to cancel or save the changes:

```svelte
<div class="stack-small">
{#if editing}
  <form on:submit|preventDefault={onSave} class="stack-small" on:keydown={(e) => e.key === 'Escape' && onCancel()}>
    <div class="form-group">
      <label for="todo-{todo.id}" class="todo-label">New name for '{todo.name}'</label>
      <input bind:value={name} type="text" id="todo-{todo.id}" autoComplete="off" class="todo-text" />
    </div>
    <div class="btn-group">
      <button class="btn todo-cancel" on:click={onCancel} type="button">
        Cancel<span class="visually-hidden">renaming {todo.name}</span>
        </button>
      <button class="btn btn\_\_primary todo-edit" type="submit" disabled={!name}>
        Save<span class="visually-hidden">new name for {todo.name}</span>
      </button>
    </div>
  </form>
{:else}
[...]
```

When the user presses the *Edit* button, the `editing` variable will be set to `true`, and Svelte will remove the markup in the `{:else}` part of the DOM and replace it with the markup in the `{#if}` section.

The `<input>`'s `value` property will be bound to the `name` variable, and the buttons to cancel and save the changes call `onCancel()` and `onSave()` respectively (we added those functions earlier):

* When `onCancel()` is invoked, `name` is restored to its original value (when passed in as a prop) and we exit editing mode (by setting `editing` to `false`).
* When `onSave()` in invoked, we run the `update()` function — passing it the modified `name` — and exit editing mode.

We also disable the *Save* button when the `<input>` is empty, using the `disabled={!name}` attribute, and allow the user to cancel the edit using the `Escape` key, like this:
```

on:keydown={(e) => e.key === 'Escape' && onCancel()}
```

We also use `todo.id` to create unique ids for the new input controls and labels.

1. The complete updated markup of our `Todo` component looks like the following. Update yours now:

```svelte
<div class="stack-small">
{#if editing}
  <!-- markup for editing todo: label, input text, Cancel and Save Button -->
  <form on:submit|preventDefault={onSave} class="stack-small" on:keydown={(e) => e.key === 'Escape' && onCancel()}>
    <div class="form-group">
      <label for="todo-{todo.id}" class="todo-label">New name for '{todo.name}'</label>
      <input bind:value={name} type="text" id="todo-{todo.id}" autoComplete="off" class="todo-text" />
    </div>
    <div class="btn-group">
      <button class="btn todo-cancel" on:click={onCancel} type="button">
        Cancel<span class="visually-hidden">renaming {todo.name}</span>
        </button>
      <button class="btn btn\_\_primary todo-edit" type="submit" disabled={!name}>
        Save<span class="visually-hidden">new name for {todo.name}</span>
      </button>
    </div>
  </form>
{:else}
  <!-- markup for displaying todo: checkbox, label, Edit and Delete Button -->
  <div class="c-cb">
    <input type="checkbox" id="todo-{todo.id}"
 on:click={onToggle} checked={todo.completed}
 >
    <label for="todo-{todo.id}" class="todo-label">{todo.name}</label>
  </div>
  <div class="btn-group">
    <button type="button" class="btn" on:click={onEdit}>
      Edit<span class="visually-hidden"> {todo.name}</span>
    </button>
    <button type="button" class="btn btn\_\_danger" on:click={onRemove}>
      Delete<span class="visually-hidden"> {todo.name}</span>
    </button>
  </div>
{/if}
</div>
```

**Note:** We could further split this into two different components, one for editing the to-do and the other for displaying it. In the end, it boils down to how comfortable you feel dealing with this level of complexity in a single component. You should also consider whether splitting it further would enable reusing this component in a different context.
2. To get the update functionality working, we have to handle the `update` event from the `Todos` component. In its `<script>` section, add this handler:

```js
function updateTodo(todo) {
  const i = todos.findIndex((t) => t.id === todo.id);
  todos[i] = { ...todos[i], ...todo };
}
```

We find the `todo` by `id` in our `todos` array, and update its content using spread syntax. In this case we could have also just used `todos[i] = todo`, but this implementation is more bullet-proof, allowing the `Todo` component to return only the updated parts of the to-do.
3. Next we have to listen for the `update` event on our `<Todo>` component call, and run our `updateTodo()` function when this occurs to change the `name` and `completed` status. Update your <Todo> call like this:

```svelte
{#each filterTodos(filter, todos) as todo (todo.id)}
<li class="todo">
  <Todo {todo} on:update={(e) => updateTodo(e.detail)} on:remove={(e) =>
 removeTodo(e.detail)} />
</li>
```

4. Try your app again, and you should see that you can delete, add, edit, cancel editing of, and toggle completion status of to-dos. And our "x out of y items completed" status heading will now update appropriately when to-dos are completed.

As you can see, it's easy to implement the "props-down, events-up" pattern in Svelte. Nevertheless, for simple components `bind` can be a good choice; Svelte will let you choose.

**Note:** Svelte provides more advanced mechanisms to share information among components: the Context API and Stores. The Context API provides a mechanism for components and their descendants to "talk" to each other without passing around data and functions as props, or dispatching lots of events. Stores allows you to share reactive data among components that are not hierarchically related. We will look at Stores later on in the series.

The code so far
---------------

### Git

To see the state of the code as it should be at the end of this article, access your copy of our repo like this:

```bash
cd mdn-svelte-tutorial/05-advanced-concepts
```

Or directly download the folder's content:

```bash
npx degit opensas/mdn-svelte-tutorial/05-advanced-concepts
```

Remember to run `npm install && npm run dev` to start your app in development mode.

### REPL

To see the current state of the code in a REPL, visit:

https://svelte.dev/repl/76cc90c43a37452e8c7f70521f88b698?version=3.23.2

Summary
-------

Now we have all of our app's required functionality in place. We can display, add, edit, and delete to-dos, mark them as completed, and filter by status.

In this article, we covered the following topics:

* Extracting functionality to a new component
* Passing information from child to parent using a handler received as a prop
* Passing information from child to parent using the `bind` directive
* Conditionally rendering blocks of markup using the `if` block
* Implementing the "props-down, events-up" communication pattern
* Creating and listening to custom events

In the next article we will continue componentizing our app and look at some advanced techniques for working with the DOM.

* Previous
* Overview: Client-side JavaScript frameworks
* Next


Introduction to client-side frameworks - Learn web development

Introduction to client-side frameworks
======================================

* Overview: Client-side JavaScript frameworks
* Next

We begin our look at frameworks with a general overview of the area, looking at a brief history of JavaScript and frameworks, why frameworks exist and what they give us, how to start thinking about choosing a framework to learn, and what alternatives there are to client-side frameworks.

|  |  |
| --- | --- |
| Prerequisites: |
 Familiarity with the core HTML,
 CSS, and
 JavaScript languages.
  |
| Objective: | To understand how client-side JavaScript frameworks came to exist, what problems they solve, what alternatives there are, and how to go about choosing one. |

A brief history
---------------

When JavaScript debuted in 1996, it added occasional interactivity and excitement to a web that was, up until then, composed of static documents. The web became not just a place to *read things*, but to *do things*. JavaScript's popularity steadily increased. Developers who worked with JavaScript wrote tools to solve the problems they faced, and packaged them into reusable packages called **libraries**, so they could share their solutions with others. This shared ecosystem of libraries helped shape the growth of the web.

Now, JavaScript is an essential part of the web, used on 98% of all websites, and the web is an essential part of modern life. Users write papers, manage their budgets, stream music, watch movies, and communicate with others over great distances instantaneously, with text, audio, or video chat. The web allows us to do things that used to be possible only in native applications installed on our computers. These modern, complex, interactive websites are often referred to as **web applications**.

The advent of modern JavaScript frameworks has made it much easier to build highly dynamic, interactive applications. A **framework** is a library that offers opinions about how software gets built. These opinions allow for predictability and homogeneity in an application; predictability allows the software to scale to an enormous size and still be maintainable; predictability and maintainability are essential for the health and longevity of software.

JavaScript frameworks power much of the impressive software on the modern web – including many of the websites you likely use every day. MDN Web Docs, which you are currently reading this on, uses the React/ReactDOM framework to power its front end.

What frameworks are out there?
------------------------------

There are many frameworks out there, but currently the "big four" are considered to be the following.

### Ember

Ember was initially released in December 2011 as a continuation of work that started in the SproutCore project. It is an older framework that has fewer users than more modern alternatives such as React and Vue, but it still enjoys a fair amount of popularity due to its stability, community support, and some clever coding principles.

Start learning Ember

### Angular

Angular is an open-source web application framework led by the Angular Team at Google and by a community of individuals and corporations. It is a complete rewrite from the same team that built AngularJS. Angular was officially released on the 14th of September 2016.

Angular is a component-based framework which uses declarative HTML templates. At build time, transparently to developers, the framework's compiler translates the templates to optimized JavaScript instructions. Angular uses TypeScript, a superset of JavaScript that we'll look at in a little more detail in the next chapter.

Start learning Angular

### Vue

After working on and learning from the original AngularJS project, Evan You released Vue in 2014. Vue is the youngest of the big four, but has enjoyed a recent uptick in popularity.

Vue, like AngularJS, extends HTML with some of its own code. Apart from that, it mainly relies on modern, standard JavaScript.

Start learning Vue

### React

Facebook released React in 2013. By this point, it had already been using React to solve many of its problems internally. Technically, React itself is *not* a framework; it's a library for rendering UI components. React is used in combination with *other* libraries to make applications — React and React Native enable developers to make mobile applications; React and ReactDOM enable them to make web applications, etc.

Because React and ReactDOM are so often used together, React is colloquially understood as a JavaScript framework. As you read through this module, we will be working with that colloquial understanding.

React extends JavaScript with HTML-like syntax, known as JSX.

Start learning React

Why do frameworks exist?
------------------------

We've discussed the environment that inspired the creation of frameworks, but not really *why* developers felt the need to make them. Exploring the why requires first examining the challenges of software development.

Consider a common kind of application: A to-do list creator, which we'll look at implementing using a variety of frameworks in future chapters. This application should allow users to do things like render a list of tasks, add a new task, and delete a task; and it must do this while reliably tracking and updating the data underlying the application. In software development, this underlying data is known as state.

Each of our goals is theoretically simple in isolation. We can iterate over the data to render it; we can add to an object to make a new task; we can use an identifier to find, edit, or delete a task. When we remember that the application has to let the user do *all* of these things through the browser, some cracks start to show. **The real problem is this: every time we change our application's state, we need to update the UI to match.**

We can examine the difficulty of this problem by looking at just *one* feature of our to-do list app: rendering a list of tasks.

The verbosity of DOM changes
----------------------------

Building HTML elements and rendering them in the browser at the appropriate time takes a surprising amount of code. Let's say that our state is an array of objects structured like this:

```js
const state = [
  {
    id: "todo-0",
    name: "Learn some frameworks!",
  },
];
```

How do we show one of those tasks to our users? We want to represent each task as a list item – an HTML `<li>` element inside of an unordered list element (a `<ul>`). How do we make it? That could look something like this:

```js
function buildTodoItemEl(id, name) {
  const item = document.createElement("li");
  const span = document.createElement("span");

  span.textContent = name;

  item.id = id;
  item.appendChild(span);
  item.appendChild(buildDeleteButtonEl(id));

  return item;
}
```

Here, we use the `document.createElement()` method to make our `<li>`, and several more lines of code to create the properties and child elements it needs.

The previous snippet references another build function: `buildDeleteButtonEl()`. It follows a similar pattern to the one we used to build a list item element:

```js
function buildDeleteButtonEl(id) {
  const button = document.createElement("button");
  button.setAttribute("type", "button");
  button.textContent "Delete";

  return button;
}
```

This button doesn't do anything yet, but it will later once we decide to implement our delete feature. The code that will render our items on the page might read something like this:

```js
function renderTodoList() {
  const frag = document.createDocumentFragment();
  state.tasks.forEach((task) => {
    const item = buildTodoItemEl(task.id, task.name);
    frag.appendChild(item);
  });

  while (todoListEl.firstChild) {
    todoListEl.removeChild(todoListEl.firstChild);
  }
  todoListEl.appendChild(frag);
}
```

We've now got almost thirty lines of code dedicated *just* to the UI – *just* to render something in the DOM – and at no point do we add classes that we could use later to style our list-items!

Working directly with the DOM, as in this example, requires understanding many things about how the DOM works: how to make elements; how to change their properties; how to put elements inside of each other; how to get them on the page. None of this code actually handles user interactions, or addresses adding or deleting a task. If we add those features, we have to remember to update our UI at the right time and in the right way.

JavaScript frameworks were created to make this kind of work a lot easier — they exist to provide a better *developer experience*. They don't bring brand-new powers to JavaScript; they give you easier access to JavaScript's powers so you can build for today's web.

If you want to see code samples from this section in action, you can check out a working version of the app on CodePen, which also allows users to add and delete new tasks.

Read more about the JavaScript features used in this section:

* `Array.forEach()`
* `Document.createDocumentFragment()`
* `Document.createElement()`
* `Element.setAttribute()`
* `Node.appendChild()`
* `Node.removeChild()`
* `Node.textContent`
Another way to build UIs
------------------------

Every JavaScript framework offers a way to write user interfaces more *declaratively*. That is, they allow you to write code that describes how your UI should look, and the framework makes it happen in the DOM behind the scenes.

The vanilla JavaScript approach to building out new DOM elements in repetition was difficult to understand at a glance. By contrast, the following block of code illustrates the way you might use Vue to describe our list of tasks:

```html
<ul>
  <li v-for="task in tasks" v-bind:key="task.id">
    <span>{{task.name}}</span>
    <button type="button">Delete</button>
  </li>
</ul>
```

That's it. This snippet reduces almost thirty lines of code down to six lines. If the curly braces and `v-` attributes here are unfamiliar to you, that's okay; you'll learn about Vue-specific syntax later on in the module. The thing to take away here is that this code looks like the UI it represents, whereas the vanilla JavaScript code does not.

Thanks to Vue, we didn't have to write our own functions for building the UI; the framework will handle that for us in an optimized, efficient way. Our only role here was to describe to Vue what each item should look like. Developers who are familiar with Vue can quickly work out what is going on when they join our project. Vue is not alone in this: using a framework improves team as well as individual efficiency.

It's possible to do things *similar* to this in vanilla JavaScript. Template literal strings make it easy to write strings of HTML that represent what the final element would look like. That might be a useful idea for something as simple as our to-do list application, but it's not maintainable for large applications that manage thousands of records of data, and could render just as many unique elements in a user interface.

Other things frameworks give us
-------------------------------

Let's look at some of the other advantages offered by frameworks. As we've alluded to before, the advantages of frameworks are achievable in vanilla JavaScript, but using a framework takes away all of the cognitive load of having to solve these problems yourself.

### Tooling

Because each of the frameworks in this module have a large, active community, each framework's ecosystem provides tooling that improves the developer experience. These tools make it easy to add things like testing (to ensure that your application behaves as it should) or linting (to ensure that your code is error-free and stylistically consistent).

**Note:** If you want to find out more details about web tooling concepts, check out our Client-side tooling overview.

### Compartmentalization

Most major frameworks encourage developers to abstract the different parts of their user interfaces into *components* — maintainable, reusable chunks of code that can communicate with one another. All the code related to a given component can live in one file (or a couple of specific files) so that you as a developer know exactly where to go to make changes to that component. In a vanilla JavaScript app, you'd have to create your own set of conventions to achieve this in an efficient, scalable way. Many JavaScript developers, if left to their own devices, could end up with all the code related to one part of the UI being spread out all over a file — or in another file altogether.

### Routing

The most essential feature of the web is that it allows users to navigate from one page to another – it is, after all, a network of interlinked documents. When you follow a link on this very website, your browser communicates with a server and fetches new content to display for you. As it does so, the URL in your address bar changes. You can save this new URL and come back to the page later on, or share it with others so they can easily find the same page. Your browser remembers your navigation history and allows you to navigate back and forth, too. This is called **server-side routing**.

Modern web applications typically do not fetch and render new HTML files — they load a single HTML shell, and continually update the DOM inside it (referred to as **single page apps**, or **SPAs**) without navigating users to new addresses on the web. Each new pseudo-webpage is usually called a *view*, and by default, no routing is done.

When an SPA is complex enough, and renders enough unique views, it's important to bring routing functionality into your application. People are used to being able to link to specific pages in an application, travel forward and backward in their navigation history, etc., and their experience suffers when these standard web features are broken. When routing is handled by a client application in this fashion, it is aptly called **client-side routing**.

It's *possible* to make a router using the native capabilities of JavaScript and the browser, but popular, actively developed frameworks have companion libraries that make routing a more intuitive part of the development process.

Things to consider when using frameworks
----------------------------------------

Being an effective web developer means using the most appropriate tools for the job. JavaScript frameworks make front-end application development easy, but they are not a silver bullet that will solve all problems. This section talks about some of the things you should consider when using frameworks. Bear in mind that you might not need a framework at all — beware that you don't end up using a framework just for the sake of it.

### Familiarity with the tool

Just like vanilla JavaScript, frameworks take time to learn and have their quirks. Before you decide to use a framework for a project, be sure you have time to learn enough of its features for it to be useful to you rather than it working against you, and be sure that your teammates are comfortable with it as well.

### Overengineering

If your web development project is a personal portfolio with a few pages, and those pages have little or no interactive capability, a framework (and all of its JavaScript) may not be necessary at all. That said, frameworks are not monolithic, and some of them are better suited to small projects than others. In an article for Smashing Magazine, Sarah Drasner writes about how Vue can replace jQuery as a tool for making small portions of a webpage interactive.

### Larger code base and abstraction

Frameworks allow you to write more declarative code – and sometimes *less* code overall – by dealing with the DOM interactions for you, behind the scenes. This abstraction is great for your experience as a developer, but it isn't free. In order to translate what you write into DOM changes, frameworks have to run their own code, which in turn makes your final piece of software larger and more computationally expensive to operate.

Some extra code is inevitable, and a framework that supports tree-shaking (removal of any code that isn't actually used in the app during the build process) will allow you to keep your applications small, but this is still a factor you need to keep in mind when considering your app's performance, especially on more network/storage-constrained devices, like mobile phones.

The abstraction of frameworks affects not only your JavaScript, but also your relationship with the very nature of the web. No matter how you build for the web, the end result, the layer that your users ultimately interact with, is HTML. Writing your whole application in JavaScript can make you lose sight of HTML and the purpose of its various tags, and lead you to produce an HTML document that is un-semantic and inaccessible. In fact, it's possible to write a fragile application that depends entirely on JavaScript and will not function without it.

Frameworks are not the source of our problems. With the wrong priorities, any application can be fragile, bloated, and inaccessible. Frameworks do, however, amplify our priorities as developers. If your priority is to make a complex web app, it's easy to do that. However, if your priorities don't carefully guard performance and accessibility, frameworks will amplify your fragility, your bloat, and your inaccessibility. Modern developer priorities, amplified by frameworks, have inverted the structure of the web in many places. Instead of a robust, content-first network of documents, the web now often puts JavaScript first and user experience last.

Accessibility on a framework-driven web
---------------------------------------

Let's build on what we said in the previous section, and talk a bit more about accessibility. Making user interfaces accessible always requires some thought and effort, and frameworks can complicate that process. You often have to employ advanced framework APIs to access native browser features like ARIA live regions or focus management.

In some cases, framework applications create accessibility barriers that do not exist for traditional websites. The biggest example of this is in client-side routing, as mentioned earlier.

With traditional (server-side) routing, navigating the web has predictable results. The browser knows to set focus to the top of the page and assistive technologies will announce the title of the page. These things happen every time you navigate to a new page.

With client-side routing, your browser is not loading new web pages, so it doesn't know that it should automatically adjust focus or announce a new page title. Framework authors have devoted immense time and labor to writing JavaScript that recreates these features, and even then, no framework has done so perfectly.

The upshot is that you should consider accessibility from the very start of *every* web project, but bear in mind that abstracted codebases that use frameworks are more likely to suffer from major accessibility issues if you don't.

How to choose a framework
-------------------------

Each of the frameworks discussed in this module takes different approaches to web application development. Each is regularly improving or changing, and each has its pros and cons. Choosing the right framework is a team- and project-dependent process, and you should do your own research to uncover what suits your needs. That said, we've identified a few questions you can ask in order to research your options more effectively:

1. What browsers does the framework support?
2. What domain-specific languages does the framework utilize?
3. Does the framework have a strong community and good docs (and other support) available?

The table in this section provides a glanceable summary of the current *browser support* offered by each framework, as well as the **domain-specific languages** with which it can be used.

Broadly, domain-specific languages (DSLs) are programming languages relevant in specific areas of software development. In the context of frameworks, DSLs are variations on JavaScript or HTML that make it easier to develop with that framework. Crucially, none of the frameworks *require* a developer to use a specific DSL, but they have almost all been designed with a specific DSL in mind. Choosing not to employ a framework's preferred DSL will mean you miss out on features that would otherwise improve your developer experience.

You should seriously consider the support matrix and DSLs of a framework when making a choice for any new project. Mismatched browser support can be a barrier to your users; mismatched DSL support can be a barrier to you and your teammates.

| Framework | Browser support | Preferred DSL | Supported DSLs | Citation |
| --- | --- | --- | --- | --- |
| Angular | Modern | TypeScript | HTML-based; TypeScript | official docs |
| React | Modern | JSX | JSX; TypeScript | official docs |
| Vue | Modern (IE9+ in Vue 2) | HTML-based | HTML-based, JSX, Pug | official docs |
| Ember | Modern (IE9+ in Ember version 2.18) | Handlebars | Handlebars, TypeScript | official docs |

**Note:** DSLs we've described as "HTML-based" do not have official names. They are not really true DSLs, but they are non-standard HTML, so we believe they are worth highlighting.

### Does the framework have a strong community?

This is perhaps the hardest metric to measure because community size does not correlate directly to easy-to-access numbers. You can check a project's number of GitHub stars or weekly npm downloads to get an idea of its popularity, but sometimes the best thing to do is search a few forums or talk to other developers. It is not just about the community's size, but also how welcoming and inclusive it is, and how good the available documentation is.

### Opinions on the web

Don't just take our word on this matter — there are discussions all over the web. The Wikimedia Foundation recently chose to use Vue for its front-end, and posted a request for comments (RFC) on framework adoption. Eric Gardner, the author of the RFC, took time to outline the needs of the Wikimedia project and why certain frameworks were good choices for the team. This RFC serves as a great example of the kind of research you should do for yourself when planning to use a front-end framework.

The State of JavaScript survey is a helpful collection of feedback from JavaScript developers. It covers many topics related to JavaScript, including data about both the use of frameworks and developer sentiment toward them. Currently, there are several years of data available, allowing you to get a sense of a framework's popularity.

The Vue team has exhaustively compared Vue to other popular frameworks. There may be some bias in this comparison (which they note), but it's a valuable resource nonetheless.

Alternatives to client-side frameworks
--------------------------------------

If you're looking for tools to expedite the web development process, and you know your project isn't going to require intensive client-side JavaScript, you could reach for one of a handful of other solutions for building the web:

* A content management system
* Server-side rendering
* A static site generator
### Content management systems

**Content-management systems** (**CMSes**) are any tools that allow a user to create content for the web without directly writing code themselves. They're a good solution for large projects, especially projects that require input from content writers who have limited coding ability, or for programmers who want to save time. They do, however, require a significant amount of time to set up, and utilizing a CMS means that you surrender at least some measure of control over the final output of your website. For example: if your chosen CMS doesn't author accessible content by default, it's often difficult to improve this.

A few popular CMS systems include Wordpress, Joomla, and Drupal.

### Server-side rendering

**Server-side rendering** (**SSR**) is an application architecture in which it is the *server*'s job to render a single-page application. This is the opposite of *client-side rendering*, which is the most common and most straightforward way to build a JavaScript application. Server-side rendering is easier on the client's device because you're only sending a rendered HTML file to them, but it can be difficult to set up compared to a client-side-rendered application.

All of the frameworks covered in this module support server-side rendering as well as client-side rendering. Check out Next.js for React, Nuxt.js for Vue (yes, it is confusing, and no, these projects are not related!), FastBoot for Ember, and Angular Universal for Angular.

**Note:** Some SSR solutions are written and maintained by the community, whereas some are "official" solutions provided by the framework's maintainer.

### Static site generators

Static site generators are programs that dynamically generate all the webpages of a multi-page website — including any relevant CSS or JavaScript — so that they can be published in any number of places. The publishing host could be a GitHub pages branch, a Netlify instance, or any private server of your choosing, for example. There are a number of advantages of this approach, mostly around performance (your user's device isn't building the page with JavaScript; it's already complete) and security (static pages have fewer attack vectors). These sites can still utilize JavaScript where they need to, but they are not *dependent* upon it. Static site generators take time to learn, just like any other tool, which can be a barrier to your development process.

Static sites can have as few or as many unique pages as you want. Just as frameworks empower you to quickly write client-side JavaScript applications, static site generators allow you a way to quickly create HTML files you would otherwise have written individually. Like frameworks, static site generators allow developers to write components that define common pieces of your web pages, and to compose those components together to create a final page. In the context of static site generators, these components are called **templates**. Web pages built by static site generators can even be home to framework applications: if you want one specific page of your statically-generated website to boot up a React application when your user visits it for example, you can do that.

Static site generators have been around for quite a long time, and they've recently seen a wave of renewed interest and innovation. A handful of powerful options are now available, such as Astro, Eleventy, Hugo, Jekyll, and Gatsby.

If you'd like to learn more about static site generators on the whole, check out Tatiana Mac's Beginner's guide to Eleventy. In the first article of the series, they explain what a static site generator is, and how it relates to other means of publishing web content.

Summary
-------

And that brings us to the end of our introduction to frameworks — we've not taught you any code yet, but hopefully we've given you a useful background on why you'd use frameworks in the first place and how to go about choosing one, and made you excited to learn more and get stuck in!

Our next article goes down to a lower level, looking at the specific kinds of features frameworks tend to offer, and why they work as they do.

* Overview: Client-side JavaScript frameworks
* Next


Filtering our to-do items - Learn web development

Filtering our to-do items
=========================

* Previous
* Overview: Client-side JavaScript frameworks
* Next

Now let's move on to adding functionality to allow users to filter their to-do items, so they can view active, completed, or all items.

|  |  |
| --- | --- |
| Prerequisites: |
 Familiarity with the core HTML,
 CSS, and
 JavaScript languages,
 knowledge of the
 terminal/command line.
  |
| Objective: | To add filtering functionality to our app. |

Our filtering code
------------------

Filtering items builds on the `filter` property, which you previously added to `app.component.ts`:

```ts
filter: 'all' | 'active' | 'done' = 'all';
```

The default value for filter is `all`, but it can also be `active` or `done`.

Adding filter controls
----------------------

 In `app.component.html`, add the following HTML below the **Add** button but above the section that lists the items.
 In the following snippet, the existing sections in your HTML are in comments so you can see exactly where to put the buttons.

```html
<!-- <button class="btn-primary" (click)="addItem(newItem.value)">Add</button>
 -->

<!-- Buttons that show all, still to do, or done items on click -->
<div class="btn-wrapper">
  <button
 class="btn btn-menu"
 [class.active]="filter == 'all'"
 (click)="filter = 'all'">
    All
  </button>

  <button
 class="btn btn-menu"
 [class.active]="filter == 'active'"
 (click)="filter = 'active'">
    To Do
  </button>

  <button
 class="btn btn-menu"
 [class.active]="filter == 'done'"
 (click)="filter = 'done'">
    Done
  </button>
</div>

<!-- <h2>{{items.length}} item(s)</h2>
 <ul>... -->
```

Clicking the buttons changes the `filter` values, which determines the `items` that show as well as the styles that Angular applies to the active button.

* If the user clicks the **All** button, all of the items show.
* If the user clicks the **To do** button, only the items with a `done` value of `false` show.
* If the user clicks the **Done** button, only the items with a `done` value of `true` show.

 A class attribute binding, using square brackets, `[]`, controls the text color of the buttons.
 The class binding, `[class.active]`, applies the `active` class when the value of `filter` matches the expression.
 For example, when the user clicks the **Done** button, which sets the `filter` value to `done`, the class binding expression of `filter == 'done'` evaluates to `true`.
 When the `filter` value is `done`, Angular applies the `active` class to the **Done** button to make the text color green.
 As soon as the user clicks on one of the other buttons, the value a `filter` is no longer `done`, so the green text color no longer applies.

Summary
-------

That was quick! Since you already had the `filter` code in `app.component.ts`, all you had to do was edit the template in order to provide controls for filtering the items. Our next — and last — article looks at how to build your Angular app ready for production, and provides further resources to carry on your learning journey.

* Previous
* Overview: Client-side JavaScript frameworks
* Next


Building Angular applications and further resources - Learn web development

Building Angular applications and further resources
===================================================

* Previous
* Overview: Client-side JavaScript frameworks

This final Angular article covers how to build an app ready for production, and provides further resources for you to continue your learning journey.

|  |  |
| --- | --- |
| Prerequisites: |
 Familiarity with the core HTML,
 CSS, and
 JavaScript languages,
 knowledge of the
 terminal/command line.
  |
| Objective: | To learn how to build your Angular app. |

Building your finished application
----------------------------------

 Now that you are finished developing your application, you can run the Angular CLI `build` command.
 When you run the `build` command in your `todo` directory, your application compiles into an output directory named `dist/`.

In the `todo` directory, run the following command at the command line:

```bash
ng build -c production
```

 The CLI compiles the application and puts the output in a new `dist` directory.
 The `--configuration production`/`-c production` flag with `ng build` gets rid of stuff you don't need for production.

Deploying your application
--------------------------

 To deploy your application, you can copy the contents of the `dist/my-project-name` folder to your web server.
 Because these files are static, you can host them on any web server capable of serving files, such as:

* Node.js
* Java
* .NET

You can use any backend such as Firebase, Google Cloud, or App Engine.

What's next
-----------

 At this point, you've built a basic application, but your Angular journey is just beginning.
 You can learn more by exploring the Angular documentation, such as:

* Tour of Heroes: An in-depth tutorial highlighting Angular features, such as using services, navigation, and getting data from a server.
* The Angular Components guides: A series of articles that cover topics such as lifecycle, component interaction, and view encapsulation.
* The Forms guides: Articles that guide you through building reactive forms in Angular, validating input, and building dynamic forms.
Summary
-------

That's it for now. We hope you had fun with Angular!

* Previous
* Overview: Client-side JavaScript frameworks