Manipulating documents - Learn web development

Manipulating documents
======================

* Previous
* Overview: Client-side web APIs
* Next

When writing web pages and apps, one of the most common things you'll want to do is manipulate the document structure in some way. This is usually done by using the Document Object Model (DOM), a set of APIs for controlling HTML and styling information that makes heavy use of the `Document` object. In this article we'll look at how to use the DOM in detail, along with some other interesting APIs that can alter your environment in interesting ways.

|  |  |
| --- | --- |
| Prerequisites: |
 A basic understanding of HTML, CSS, and
 JavaScript — including JavaScript objects.
  |
| Objective: |
 To gain familiarity with the core DOM APIs, and the other APIs commonly
 associated with DOM and document manipulation.
  |

The important parts of a web browser
------------------------------------

Web browsers are very complicated pieces of software with a lot of moving parts, many of which can't be controlled or manipulated by a web developer using JavaScript. You might think that such limitations are a bad thing, but browsers are locked down for good reasons, mostly centering around security. Imagine if a website could get access to your stored passwords or other sensitive information, and log into websites as if it were you?

Despite the limitations, Web APIs still give us access to a lot of functionality that enable us to do a great many things with web pages. There are a few really obvious bits you'll reference regularly in your code — consider the following diagram, which represents the main parts of a browser directly involved in viewing web pages:

![Important parts of web browser; the document is the web page. The window includes the entire document and also the tab. The navigator is the browser, which includes the window (which includes the document) and all other windows.](/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents/document-window-navigator.png)

* The window is the browser tab that a web page is loaded into; this is represented in JavaScript by the `Window` object. Using methods available on this object you can do things like return the window's size (see `Window.innerWidth` and `Window.innerHeight`), manipulate the document loaded into that window, store data specific to that document on the client-side (for example using a local database or other storage mechanism), attach an event handler to the current window, and more.
* The navigator represents the state and identity of the browser (i.e. the user-agent) as it exists on the web. In JavaScript, this is represented by the `Navigator` object. You can use this object to retrieve things like the user's preferred language, a media stream from the user's webcam, etc.
* The document (represented by the DOM in browsers) is the actual page loaded into the window, and is represented in JavaScript by the `Document` object. You can use this object to return and manipulate information on the HTML and CSS that comprises the document, for example get a reference to an element in the DOM, change its text content, apply new styles to it, create new elements and add them to the current element as children, or even delete it altogether.

In this article we'll focus mostly on manipulating the document, but we'll show a few other useful bits besides.

The document object model
-------------------------

The document currently loaded in each one of your browser tabs is represented by a document object model. This is a "tree structure" representation created by the browser that enables the HTML structure to be easily accessed by programming languages — for example the browser itself uses it to apply styling and other information to the correct elements as it renders a page, and developers like you can manipulate the DOM with JavaScript after the page has been rendered.

We have created a simple example page at dom-example.html (see it live also). Try opening this up in your browser — it is a very simple page containing a `<section>` element inside which you can find an image, and a paragraph with a link inside. The HTML source code looks like this:

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>Simple DOM example</title>
  </head>
  <body>
    <section>
      <img
 src="dinosaur.png"
 alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth." />
      <p>
        Here we will add a link to the
        <a href="https://www.mozilla.org/">Mozilla homepage</a>
      </p>
    </section>
  </body>
</html>
```

The DOM on the other hand looks like this:

![Tree structure representation of Document Object Model: The top node is the doctype and HTML element. Child nodes of the HTML include head and body. Each child element is a branch. All text, even white space, is shown as well.](/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents/dom-screenshot.png)

**Note:** This DOM tree diagram was created using Ian Hickson's Live DOM viewer.

Each entry in the tree is called a **node**. You can see in the diagram above that some nodes represent elements (identified as `HTML`, `HEAD`, `META` and so on) and others represent text (identified as `#text`). There are other types of nodes as well, but these are the main ones you'll encounter.

Nodes are also referred to by their position in the tree relative to other nodes:

* **Root node**: The top node in the tree, which in the case of HTML is always the `HTML` node (other markup vocabularies like SVG and custom XML will have different root elements).
* **Child node**: A node *directly* inside another node. For example, `IMG` is a child of `SECTION` in the above example.
* **Descendant node**: A node *anywhere* inside another node. For example, `IMG` is a child of `SECTION` in the above example, and it is also a descendant. `IMG` is not a child of `BODY`, as it is two levels below it in the tree, but it is a descendant of `BODY`.
* **Parent node**: A node which has another node inside it. For example, `BODY` is the parent node of `SECTION` in the above example.
* **Sibling nodes**: Nodes that sit on the same level in the DOM tree. For example, `IMG` and `P` are siblings in the above example.

It is useful to familiarize yourself with this terminology before working with the DOM, as a number of the code terms you'll come across make use of them. You may have also come across them if you have studied CSS (e.g. descendant selector, child selector).

Active learning: Basic DOM manipulation
---------------------------------------

To start learning about DOM manipulation, let's begin with a practical example.

1. Take a local copy of the dom-example.html page and the image that goes along with it.
2. Add a `<script></script>` element just above the closing `</body>` tag.
3. To manipulate an element inside the DOM, you first need to select it and store a reference to it inside a variable. Inside your script element, add the following line:

```js
const link = document.querySelector("a");
```

4. Now we have the element reference stored in a variable, we can start to manipulate it using properties and methods available to it (these are defined on interfaces like `HTMLAnchorElement` in the case of `<a>` element, its more general parent interface `HTMLElement`, and `Node` — which represents all nodes in a DOM). First of all, let's change the text inside the link by updating the value of the `Node.textContent` property. Add the following line below the previous one:

```js
link.textContent = "Mozilla Developer Network";
```

5. We should also change the URL the link is pointing to, so that it doesn't go to the wrong place when it is clicked on. Add the following line, again at the bottom:

```js
link.href = "https://developer.mozilla.org";
```

Note that, as with many things in JavaScript, there are many ways to select an element and store a reference to it in a variable. `Document.querySelector()` is the recommended modern approach. It is convenient because it allows you to select elements using CSS selectors. The above `querySelector()` call will match the first `<a>` element that appears in the document. If you wanted to match and do things to multiple elements, you could use `Document.querySelectorAll()`, which matches every element in the document that matches the selector, and stores references to them in an array-like object called a `NodeList`.

There are older methods available for grabbing element references, such as:

* `Document.getElementById()`, which selects an element with a given `id` attribute value, e.g. `<p id="myId">My paragraph</p>`. The ID is passed to the function as a parameter, i.e. `const elementRef = document.getElementById('myId')`.
* `Document.getElementsByTagName()`, which returns an array-like object containing all the elements on the page of a given type, for example `<p>`s, `<a>`s, etc. The element type is passed to the function as a parameter, i.e. `const elementRefArray = document.getElementsByTagName('p')`.

These two work better in older browsers than the modern methods like `querySelector()`, but are not as convenient. Have a look and see what others you can find!

### Creating and placing new nodes

The above has given you a little taste of what you can do, but let's go further and look at how we can create new elements.

1. Going back to the current example, let's start by grabbing a reference to our `<section>` element — add the following code at the bottom of your existing script (do the same with the other lines too):

```js
const sect = document.querySelector("section");
```

2. Now let's create a new paragraph using `Document.createElement()` and give it some text content in the same way as before:

```js
const para = document.createElement("p");
para.textContent = "We hope you enjoyed the ride.";
```

3. You can now append the new paragraph at the end of the section using `Node.appendChild()`:

```js
sect.appendChild(para);
```

4. Finally for this part, let's add a text node to the paragraph the link sits inside, to round off the sentence nicely. First we will create the text node using `Document.createTextNode()`:

```js
const text = document.createTextNode(
  " — the premier source for web development knowledge.",
);
```

5. Now we'll grab a reference to the paragraph the link is inside, and append the text node to it:

```js
const linkPara = document.querySelector("p");
linkPara.appendChild(text);
```

That's most of what you need for adding nodes to the DOM — you'll make a lot of use of these methods when building dynamic interfaces (we'll look at some examples later).

### Moving and removing elements

There may be times when you want to move nodes, or delete them from the DOM altogether. This is perfectly possible.

If we wanted to move the paragraph with the link inside it to the bottom of the section, we could do this:

```js
sect.appendChild(linkPara);
```

This moves the paragraph down to the bottom of the section. You might have thought it would make a second copy of it, but this is not the case — `linkPara` is a reference to the one and only copy of that paragraph. If you wanted to make a copy and add that as well, you'd need to use `Node.cloneNode()` instead.

Removing a node is pretty simple as well, at least when you have a reference to the node to be removed and its parent. In our current case, we just use `Node.removeChild()`, like this:

```js
sect.removeChild(linkPara);
```

When you want to remove a node based only on a reference to itself, which is fairly common, you can use `Element.remove()`:

```js
linkPara.remove();
```

This method is not supported in older browsers. They have no method to tell a node to remove itself, so you'd have to do the following.

```js
linkPara.parentNode.removeChild(linkPara);
```

Have a go at adding the above lines to your code.

### Manipulating styles

It is possible to manipulate CSS styles via JavaScript in a variety of ways.

To start with, you can get a list of all the stylesheets attached to a document using `Document.stylesheets`, which returns an array-like object with `CSSStyleSheet` objects. You can then add/remove styles as wished. However, we're not going to expand on those features because they are a somewhat archaic and difficult way to manipulate style. There are much easier ways.

The first way is to add inline styles directly onto elements you want to dynamically style. This is done with the `HTMLElement.style` property, which contains inline styling information for each element in the document. You can set properties of this object to directly update element styles.

1. As an example, try adding these lines to our ongoing example:

```js
para.style.color = "white";
para.style.backgroundColor = "black";
para.style.padding = "10px";
para.style.width = "250px";
para.style.textAlign = "center";
```

2. Reload the page and you'll see that the styles have been applied to the paragraph. If you look at that paragraph in your browser's Page Inspector/DOM inspector, you'll see that these lines are indeed adding inline styles to the document:

```html
<p
 style="color: white; background-color: black; padding: 10px; width: 250px; text-align: center;">
  We hope you enjoyed the ride.
</p>
```

**Note:** Notice how the JavaScript property versions of the CSS styles are written in lower camel case whereas the CSS versions are hyphenated (kebab-case) (e.g. `backgroundColor` versus `background-color`). Make sure you don't get these mixed up, otherwise it won't work.

There is another common way to dynamically manipulate styles on your document, which we'll look at now.

1. Delete the previous five lines you added to the JavaScript.
2. Add the following inside your HTML `<head>`:

```html
<style>
 .highlight {
 color: white;
 background-color: black;
 padding: 10px;
 width: 250px;
 text-align: center;
 }
</style>
```

3. Now we'll turn to a very useful method for general HTML manipulation — `Element.setAttribute()` — this takes two arguments, the attribute you want to set on the element, and the value you want to set it to. In this case we will set a class name of highlight on our paragraph:

```js
para.setAttribute("class", "highlight");
```

4. Refresh your page, and you'll see no change — the CSS is still applied to the paragraph, but this time by giving it a class that is selected by our CSS rule, not as inline CSS styles.

Which method you choose is up to you; both have their advantages and disadvantages. The first method takes less setup and is good for simple uses, whereas the second method is more purist (no mixing CSS and JavaScript, no inline styles, which are seen as a bad practice). As you start building larger and more involved apps, you will probably start using the second method more, but it is really up to you.

At this point, we haven't really done anything useful! There is no point using JavaScript to create static content — you might as well just write it into your HTML and not use JavaScript. It is more complex than HTML, and creating your content with JavaScript also has other issues attached to it (such as not being readable by search engines).

In the next section we will look at a more practical use of DOM APIs.

**Note:** You can find our finished version of the dom-example.html demo on GitHub (see it live also).

Active learning: A dynamic shopping list
----------------------------------------

In this challenge we want to make a simple shopping list example that allows you to dynamically add items to the list using a form input and button. When you add an item to the input and press the button:

* The item should appear in the list.
* Each item should be given a button that can be pressed to delete that item off the list.
* The input should be emptied and focused ready for you to enter another item.

The finished demo will look something like this:

![Demo layout of a shopping list. A 'my shopping list' header followed by 'Enter a new item' with an input field and 'add item' button. The list of already added items is below, each with a corresponding delete button. ](/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents/shopping-list.png)

To complete the exercise, follow the steps below, and make sure that the list behaves as described above.

1. To start with, download a copy of our shopping-list.html starting file and make a copy of it somewhere. You'll see that it has some minimal CSS, a div with a label, input, and button, and an empty list and `<script>` element. You'll be making all your additions inside the script.
2. Create three variables that hold references to the list (`<ul>`), `<input>`, and `<button>` elements.
3. Create a function that will run in response to the button being clicked.
4. Inside the function body, start off by storing the current value of the input element in a variable.
5. Next, empty the input element by setting its value to an empty string — `''`.
6. Create three new elements — a list item (`<li>`), `<span>`, and `<button>`, and store them in variables.
7. Append the span and the button as children of the list item.
8. Set the text content of the span to the input element value you saved earlier, and the text content of the button to 'Delete'.
9. Append the list item as a child of the list.
10. Attach an event handler to the delete button so that, when clicked, it will delete the entire list item (`<li>...</li>`).
11. Finally, use the `focus()` method to focus the input element ready for entering the next shopping list item.

**Note:** If you get really stuck, have a look at our finished shopping list (see it running live also).

Summary
-------

We have reached the end of our study of document and DOM manipulation. At this point you should understand what the important parts of a web browser are with respect to controlling documents and other aspects of the user's web experience. Most importantly, you should understand what the Document Object Model is, and how to manipulate it to create useful functionality.

See also
--------

There are lots more features you can use to manipulate your documents. Check out some of our references and see what you can discover:

* `Document`
* `Window`
* `Node`
* `HTMLElement`, `HTMLInputElement`, `HTMLImageElement`, etc.

(See our Web API index for the full list of Web APIs documented on MDN!)

* Previous
* Overview: Client-side web APIs
* Next


Fetching data from the server - Learn web development

Fetching data from the server
=============================

* Previous
* Overview: Client-side web APIs
* Next

Another very common task in modern websites and applications is retrieving individual data items from the server to update sections of a webpage without having to load an entire new page. This seemingly small detail has had a huge impact on the performance and behavior of sites, so in this article, we'll explain the concept and look at technologies that make it possible: in particular, the Fetch API.

|  |  |
| --- | --- |
| Prerequisites: |
 JavaScript basics (see
 first steps,
 building blocks,
 JavaScript objects),
 the
 basics of Client-side APIs |
| Objective: |
 To learn how to fetch data from the server and use it to update the
 contents of a web page.
  |

What is the problem here?
-------------------------

A web page consists of an HTML page and (usually) various other files, such as stylesheets, scripts, and images. The basic model of page loading on the Web is that your browser makes one or more HTTP requests to the server for the files needed to display the page, and the server responds with the requested files. If you visit another page, the browser requests the new files, and the server responds with them.

![Traditional page loading](/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data/traditional-loading.svg)

This model works perfectly well for many sites. But consider a website that's very data-driven. For example, a library website like the Vancouver Public Library. Among other things you could think of a site like this as a user interface to a database. It might let you search for a particular genre of book, or might show you recommendations for books you might like, based on books you've previously borrowed. When you do this, it needs to update the page with the new set of books to display. But note that most of the page content — including items like the page header, sidebar, and footer — stays the same.

The trouble with the traditional model here is that we'd have to fetch and load the entire page, even when we only need to update one part of it. This is inefficient and can result in a poor user experience.

So instead of the traditional model, many websites use JavaScript APIs to request data from the server and update the page content without a page load. So when the user searches for a new product, the browser only requests the data which is needed to update the page — the set of new books to display, for instance.

![Using fetch to update pages](/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data/fetch-update.svg)

The main API here is the Fetch API. This enables JavaScript running in a page to make an HTTP request to a server to retrieve specific resources. When the server provides them, the JavaScript can use the data to update the page, typically by using DOM manipulation APIs. The data requested is often JSON, which is a good format for transferring structured data, but can also be HTML or just text.

This is a common pattern for data-driven sites such as Amazon, YouTube, eBay, and so on. With this model:

* Page updates are a lot quicker and you don't have to wait for the page to refresh, meaning that the site feels faster and more responsive.
* Less data is downloaded on each update, meaning less wasted bandwidth. This may not be such a big issue on a desktop on a broadband connection, but it's a major issue on mobile devices and in countries that don't have ubiquitous fast internet service.

**Note:** In the early days, this general technique was known as Asynchronous JavaScript and XML (Ajax), because it tended to request XML data. This is normally not the case these days (you'd be more likely to request JSON), but the result is still the same, and the term "Ajax" is still often used to describe the technique.

To speed things up even further, some sites also store assets and data on the user's computer when they are first requested, meaning that on subsequent visits they use the local versions instead of downloading fresh copies every time the page is first loaded. The content is only reloaded from the server when it has been updated.

The Fetch API
-------------

Let's walk through a couple of examples of the Fetch API.

### Fetching text content

For this example, we'll request data out of a few different text files and use them to populate a content area.

This series of files will act as our fake database; in a real application, we'd be more likely to use a server-side language like PHP, Python, or Node to request our data from a database. Here, however, we want to keep it simple and concentrate on the client-side part of this.

To begin this example, make a local copy of fetch-start.html and the four text files — verse1.txt, verse2.txt, verse3.txt, and verse4.txt — in a new directory on your computer. In this example, we will fetch a different verse of the poem (which you may well recognize) when it's selected in the drop-down menu.

Just inside the `<script>` element, add the following code. This stores references to the `<select>` and `<pre>` elements and adds a listener to the `<select>` element, so that when the user selects a new value, the new value is passed to the function named `updateDisplay()` as a parameter.

```js
const verseChoose = document.querySelector("select");
const poemDisplay = document.querySelector("pre");

verseChoose.addEventListener("change", () => {
  const verse = verseChoose.value;
  updateDisplay(verse);
});
```

Let's define our `updateDisplay()` function. First of all, put the following beneath your previous code block — this is the empty shell of the function.

```js
function updateDisplay(verse) {

}
```

We'll start our function by constructing a relative URL pointing to the text file we want to load, as we'll need it later. The value of the `<select>` element at any time is the same as the text inside the selected `<option>` (unless you specify a different value in a value attribute) — so for example "Verse 1". The corresponding verse text file is "verse1.txt", and is in the same directory as the HTML file, therefore just the file name will do.

However, web servers tend to be case-sensitive, and the file name doesn't have a space in it. To convert "Verse 1" to "verse1.txt" we need to convert the 'V' to lower case, remove the space, and add ".txt" on the end. This can be done with `replace()`, `toLowerCase()`, and template literal. Add the following lines inside your `updateDisplay()` function:

```js
verse = verse.replace(" ", "").toLowerCase();
const url = `${verse}.txt`;
```

Finally we're ready to use the Fetch API:

```js
// Call `fetch()`, passing in the URL.
fetch(url)
  // fetch() returns a promise. When we have received a response from the server,
  // the promise's `then()` handler is called with the response.
  .then((response) => {
    // Our handler throws an error if the request did not succeed.
    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }
    // Otherwise (if the response succeeded), our handler fetches the response
    // as text by calling response.text(), and immediately returns the promise
    // returned by `response.text()`.
    return response.text();
  })
  // When response.text() has succeeded, the `then()` handler is called with
  // the text, and we copy it into the `poemDisplay` box.
  .then((text) => {
    poemDisplay.textContent = text;
  })
  // Catch any errors that might happen, and display a message
  // in the `poemDisplay` box.
  .catch((error) => {
    poemDisplay.textContent = `Could not fetch verse: ${error}`;
  });
```

There's quite a lot to unpack in here.

First, the entry point to the Fetch API is a global function called `fetch()`, that takes the URL as a parameter (it takes another optional parameter for custom settings, but we're not using that here).

Next, `fetch()` is an asynchronous API which returns a `Promise`. If you don't know what that is, read the module on asynchronous JavaScript, and in particular the article on promises, then come back here. You'll find that article also talks about the `fetch()` API!

So because `fetch()` returns a promise, we pass a function into the `then()` method of the returned promise. This method will be called when the HTTP request has received a response from the server. In the handler, we check that the request succeeded, and throw an error if it didn't. Otherwise, we call `response.text()`, to get the response body as text.

It turns out that `response.text()` is *also* asynchronous, so we return the promise it returns, and pass a function into the `then()` method of this new promise. This function will be called when the response text is ready, and inside it we will update our `<pre>` block with the text.

Finally, we chain a `catch()` handler at the end, to catch any errors thrown in either of the asynchronous functions we called or their handlers.

One problem with the example as it stands is that it won't show any of the poem when it first loads. To fix this, add the following two lines at the bottom of your code (just above the closing `</script>` tag) to load verse 1 by default, and make sure the `<select>` element always shows the correct value:

```js
updateDisplay("Verse 1");
verseChoose.value = "Verse 1";
```

#### Serving your example from a server

Modern browsers will not run HTTP requests if you just run the example from a local file. This is because of security restrictions (for more on web security, read Website security).

To get around this, we need to test the example by running it through a local web server. To find out how to do this, read our guide to setting up a local testing server.

### The can store

In this example we have created a sample site called The Can Store — it's a fictional supermarket that only sells canned goods. You can find this example live on GitHub, and see the source code.

![A fake e-commerce site showing search options in the left hand column, and product search results in the right-hand column.](/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data/can-store.png)

By default, the site displays all the products, but you can use the form controls in the left-hand column to filter them by category, or search term, or both.

There is quite a lot of complex code that deals with filtering the products by category and search terms, manipulating strings so the data displays correctly in the UI, etc. We won't discuss all of it in the article, but you can find extensive comments in the code (see can-script.js).

We will, however, explain the Fetch code.

The first block that uses Fetch can be found at the start of the JavaScript:

```js
fetch("products.json")
  .then((response) => {
    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }
    return response.json();
  })
  .then((json) => initialize(json))
  .catch((err) => console.error(`Fetch problem: ${err.message}`));
```

The `fetch()` function returns a promise. If this completes successfully, the function inside the first `.then()` block contains the `response` returned from the network.

Inside this function we:

* check that the server didn't return an error (such as `404 Not Found`). If it did, we throw the error.
* call `json()` on the response. This will retrieve the data as a JSON object. We return the promise returned by `response.json()`.

Next we pass a function into the `then()` method of that returned promise. This function will be passed an object containing the response data as JSON, which we pass into the `initialize()` function. This function which starts the process of displaying all the products in the user interface.

To handle errors, we chain a `.catch()` block onto the end of the chain. This runs if the promise fails for some reason. Inside it, we include a function that is passed as a parameter, an `err` object. This `err` object can be used to report the nature of the error that has occurred, in this case we do it with a simple `console.error()`.

However, a complete website would handle this error more gracefully by displaying a message on the user's screen and perhaps offering options to remedy the situation, but we don't need anything more than a simple `console.error()`.

You can test the failure case yourself:

1. Make a local copy of the example files.
2. Run the code through a web server (as described above, in Serving your example from a server).
3. Modify the path to the file being fetched, to something like 'produc.json' (make sure it is misspelled).
4. Now load the index file in your browser (via `localhost:8000`) and look in your browser developer console. You'll see a message similar to "Fetch problem: HTTP error: 404".

The second Fetch block can be found inside the `fetchBlob()` function:

```js
fetch(url)
  .then((response) => {
    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }
    return response.blob();
  })
  .then((blob) => showProduct(blob, product))
  .catch((err) => console.error(`Fetch problem: ${err.message}`));
```

This works in much the same way as the previous one, except that instead of using `json()`, we use `blob()`. In this case we want to return our response as an image file, and the data format we use for that is Blob (the term is an abbreviation of "Binary Large Object" and can basically be used to represent large file-like objects, such as images or video files).

Once we've successfully received our blob, we pass it into our `showProduct()` function, which displays it.

The XMLHttpRequest API
----------------------

Sometimes, especially in older code, you'll see another API called `XMLHttpRequest` (often abbreviated as "XHR") used to make HTTP requests. This predated Fetch, and was really the first API widely used to implement AJAX. We recommend you use Fetch if you can: it's a simpler API and has more features than `XMLHttpRequest`. We won't go through an example that uses `XMLHttpRequest`, but we will show you what the `XMLHttpRequest` version of our first can store request would look like:

```js
const request = new XMLHttpRequest();

try {
  request.open("GET", "products.json");

  request.responseType = "json";

  request.addEventListener("load", () => initialize(request.response));
  request.addEventListener("error", () => console.error("XHR error"));

  request.send();
} catch (error) {
  console.error(`XHR error ${request.status}`);
}
```

There are five stages to this:

1. Create a new `XMLHttpRequest` object.
2. Call its `open()` method to initialize it.
3. Add an event listener to its `load` event, which fires when the response has completed successfully. In the listener we call `initialize()` with the data.
4. Add an event listener to its `error` event, which fires when the request encounters an error
5. Send the request.

We also have to wrap the whole thing in the try...catch block, to handle any errors thrown by `open()` or `send()`.

Hopefully you think the Fetch API is an improvement over this. In particular, see how we have to handle errors in two different places.

Summary
-------

This article shows how to start working with Fetch to fetch data from the server.

See also
--------

There are however a lot of different subjects discussed in this article, which has only really scratched the surface. For a lot more detail on these subjects, try the following articles:

* Using Fetch
* Promises
* Working with JSON data
* An overview of HTTP
* Server-side website programming
* Previous
* Overview: Client-side web APIs
* Next


Cross browser testing - Learn web development

Cross browser testing
=====================

This module focuses on testing web projects across different browsers. We look at identifying your target audience (e.g. what users, browsers, and devices do you most need to worry about?), how to go about doing testing, the main issues that you'll face with different types of code and how to mitigate them, what tools are most useful in helping you test and fix problems, and how to use automation to speed up testing.

#### Looking to become a front-end web developer?

 We have put together a course that includes all the essential information you need to
 work towards your goal.

**Get started**

Prerequisites
-------------

You should really learn the basics of the core HTML, CSS, and JavaScript languages first before attempting to use the tools detailed here.

Guides
------

Introduction to cross browser testing

This article starts the module off by providing an overview of the topic of cross browser testing, answering questions such as "what is cross browser testing?", "what are the most common types of problems you'll encounter?", and "what are the main approaches for testing, identifying, and fixing problems?"

Strategies for carrying out testing

Next, we drill down into carrying out testing, looking at identifying a target audience (e.g. what browsers, devices, and other segments should you make sure are tested), lo-fi testing strategies (get yourself a range of devices and some virtual machines and do ad hoc tests when needed), higher tech strategies (automation, using dedicated testing apps), and testing with user groups.

Handling common HTML and CSS problems

With the scene set, we'll now look specifically at the common cross-browser problems you will come across in HTML and CSS code, and what tools can be used to prevent problems from happening, or fix problems that occur. This includes linting code, handling CSS prefixes, using browser dev tools to track down problems, using polyfills to add support into browsers, tackling responsive design problems, and more.

Handling common JavaScript problems

Now we'll look at common cross-browser JavaScript problems and how to fix them. This includes information on using browser dev tools to track down and fix problems, using polyfills and libraries to work around problems, getting modern JavaScript features working in older browsers, and more.

Handling common accessibility problems

Next we turn our attention to accessibility, providing information on common problems, how to do simple testing, and how to make use of auditing/automation tools for finding accessibility issues.

Implementing feature detection

Feature detection involves working out whether a browser supports a certain block of code, and running different code dependent on whether it does (or doesn't), so that the browser can always provide a working experience rather than crashing/erroring in some browsers. This article details how to write your own simple feature detection, how to use a library to speed up implementation, and native features for feature detection such as `@supports`.

Introduction to automated testing

Manually running tests on several browsers and devices, several times per day, can get tedious and time-consuming. To handle this efficiently, you should become familiar with automation tools. In this article, we look at what is available, how to use task runners, and the basics of how to use commercial browser test automation apps such as Sauce Labs and Browser Stack.

Setting up your own test automation environment

In this article, we will teach you how to install your own automation environment and run your own tests using Selenium/WebDriver and a testing library such as selenium-webdriver for Node. We will also look at how to integrate your local testing environment with commercial apps like the ones discussed in the previous article.


Git and GitHub - Learn web development

Git and GitHub
==============

All developers will use some kind of **version control system** (**VCS**), a tool to allow them to collaborate with other developers on a project without the danger of them overwriting each other's work, and roll back to previous versions of the code base if a problem is discovered later on. The most popular VCS (at least among web developers) is **Git**, along with **GitHub**, a site that provides hosting for your repositories and several tools for working with them. This module aims to teach you what you need to know about both of them.

Overview
--------

VCSes are essential for software development:

* It is rare that you will work on a project completely on your own, and as soon as you start working with other people you start to run the risk of conflicting with each other's work — this is when both of you try to update the same piece of code at the same time. You need to have some kind of mechanism in place to manage the occurrences, and help avoid loss of work as a result.
* When working on a project on your own or with others, you'll want to be able to back up the code in a central place, so it is not lost if your computer breaks.
* You will also want to be able to roll back to earlier versions if a problem is later discovered. You might have started doing this in your own work by creating different versions of the same file, e.g. `myCode.js`, `myCode_v2.js`, `myCode_v3.js`, `myCode_final.js`, `myCode_really_really_final.js`, etc., but this is really error-prone and unreliable.
* Different team members will commonly want to create their own separate versions of the code (called **branches** in Git), work on a new feature in that version, and then get it merged in a controlled manner (in GitHub we use **pull requests**) with the master version when they are done with it.

VCSes provide tools to meet the above needs. Git is an example of a VCS, and GitHub is a website + infrastructure that provides a Git server plus a number of really useful tools for working with git repositories individually or in teams, such as reporting issues with the code, reviewing tools, project management features such as assigning tasks and task statuses, and more.

**Note:** Git is actually a *distributed* version control system, meaning that a complete copy of the repository containing the codebase is made on your computer (and everyone else's). You make changes to your own copy and then push those changes back up to the server, where an administrator will decide whether to merge your changes with the master copy.

#### Looking to become a front-end web developer?

 We have put together a course that includes all the essential information you need to
 work towards your goal.

**Get started**

Prerequisites
-------------

To use Git and GitHub, you need:

* A desktop computer with Git installed on it (see the Git downloads page).
* A tool to use Git. Depending on how you like to work, you could use a Git GUI client (we'd recommend GitHub Desktop, SourceTree or Git Kraken) or just stick to using a terminal window. In fact, it is probably useful for you to get to know at least the basics of git terminal commands, even if you intend to use a GUI.
* A GitHub account. If you haven't already got one, sign up now using the provided link.

In terms of prerequisite knowledge, you don't need to know anything about web development, Git/GitHub, or VCSes to start this module. However, it is recommended that you know some coding so that you have reasonable computer literacy, and some code to store in your repositories!

It is also preferable that you have some basic terminal knowledge, so for example moving between directories, creating files, and modifying the system `PATH`.

**Note:** GitHub is not the only site/toolset you can use with Git. There are other alternatives such as GitLab that you could try, and you could also try setting your own Git server up and using it instead of GitHub. We've only stuck with GitHub in this course to provide a single way that works.

Guides
------

Note that the links below take you to resources on external sites. Eventually, we are aiming to have our own dedicated Git/GitHub course, but for now, these will help you get to grips with the subject at hand.

Hello, World (from GitHub)

This is a good place to start — this practical guide gets you to jump right into using GitHub, learning the basics of Git such as creating repositories and branches, making commits, and opening and merging pull requests.

Git Handbook (from GitHub)

This Git Handbook goes into a little more depth, explaining what a VCS is, what a repository is, how the basic GitHub model works, Git commands and examples, and more.

Forking Projects (from GitHub)

Forking projects is essential when you want to contribute to someone else's code. This guide explains how.

About Pull Requests (from GitHub)

A useful guide to managing pull requests, the way that your suggested code changes are delivered to people's repositories for consideration.

Mastering issues (from GitHub)

Issues are like a forum for your GitHub project, where people can ask questions and report problems, and you can manage updates (for example assigning people to fix issues, clarifying the issue, letting people know things are fixed). This article tells you what you need to know about issues.

**Note:** There is **a lot more** that you can do with Git and GitHub, but we feel that the above represents the minimum you need to know to start using Git effectively. As you get deeper into Git, you'll start to realize that it is easy to go wrong when you start using more complicated commands. Don't worry, even professional web developers find Git confusing sometimes, and often solve problems by searching for solutions on the web, or consulting sites like Flight rules for Git and Dangit, git!

See also
--------

* Understanding the GitHub flow
* Git command list
* Mastering markdown (the text format you write in on PR, issue comments, and `.md` files).
* Getting Started with GitHub Pages (how to publish demos and websites on GitHub).
* Learn Git branching
* Flight rules for Git (a very useful compendium of ways to achieve specific things in Git, including how to correct things when you went wrong).
* Dangit, git! (another useful compendium, specifically of ways to correct things when you went wrong).


Understanding client-side web development tools - Learn web development

Understanding client-side web development tools
===============================================

Client-side tooling can be intimidating, but this series of articles aims to illustrate the purpose of some of the most common client-side tool types, explain the tools you can chain together, how to install them using package managers, and control them using the command line. We finish up by providing a complete toolchain example showing you how to get productive.

Prerequisites
-------------

You should really learn the basics of the core HTML, CSS, and JavaScript languages first before attempting to use the tools detailed here.

#### Looking to become a front-end web developer?

 We have put together a course that includes all the essential information you need to
 work towards your goal.

**Get started**

Guides
------

1. Client-side tooling overview

In this article we provide an overview of modern web tooling, what kinds of tools are available and where you'll meet them in the lifecycle of web app development, and how to find help with individual tools.

2. Command line crash course

In your development process you'll undoubtedly be required to run some command in the terminal (or on the "command line" — these are effectively the same thing). This article provides an introduction to the terminal, the essential commands you'll need to enter into it, how to chain commands together, and how to add your own command line interface (CLI) tools.

3. Package management basics

In this article we'll look at package managers in some detail to understand how we can use them in our own projects — to install project tool dependencies, keep them up-to-date, and more.

4. Introducing a complete toolchain

In the final couple of articles in the series we will solidify your tooling knowledge by walking you through the process of building up a sample case study toolchain. We'll go all the way from setting up a sensible development environment and putting transformation tools in place to actually deploying your app on Netlify. In this article we'll introduce the case study, set up our development environment, and set up our code transformation tools.

5. Deploying our app

In the final article in our series, we take the example toolchain we built up in the previous article and add to it so that we can deploy our sample app. We push the code to GitHub, deploy it using Netlify, and even show you how to add a simple test into the process.


Understanding client-side JavaScript frameworks - Learn web development

Understanding client-side JavaScript frameworks
===============================================

JavaScript frameworks are an essential part of modern front-end web development, providing developers with tried and tested tools for building scalable, interactive web applications. Many modern companies use frameworks as a standard part of their tooling, so many front-end development jobs now require framework experience. In this set of articles, we are aiming to give you a comfortable starting point to help you begin learning frameworks.

As an aspiring front-end developer, it can be hard to work out where to begin when learning frameworks — there are so many frameworks to choose from, new ones appear all the time, they mostly work in a similar way but do some things differently, and there are some specific things to be careful about when using frameworks.

We are not aiming to exhaustively teach you everything you need to know about React/ReactDOM, or Vue, or some other specific framework; the framework teams' own docs (and other resources) do that job already. Instead, we want to back up and first answer more fundamental questions such as:

* Why should I use a framework? What problems do they solve for me?
* What questions should I ask when trying to choose a framework? Do I even need to use a framework?
* What features do frameworks have? How do they work in general, and how do frameworks' implementations of these features differ?
* How do they relate to "vanilla" JavaScript or HTML?

After that, we'll provide some tutorials covering the essentials of some of the different framework choices, to provide you with enough context and familiarity to start going into greater depth yourself. We want you to go forward and learn about frameworks in a pragmatic way that doesn't forget about web platform fundamental best practices such as accessibility.

**Get started now, with "Introduction to client-side frameworks"**

Prerequisites
-------------

You should really learn the basics of the core web languages first before attempting to move on to learning client-side frameworks — HTML, CSS, and especially JavaScript.

Your code will be richer and more professional as a result, and you'll be able to troubleshoot problems with more confidence if you understand the fundamental web platform features that the frameworks are building on top of.

#### Looking to become a front-end web developer?

 We have put together a course that includes all the essential information you need to
 work towards your goal.

**Get started**

Introductory guides
-------------------

1. Introduction to client-side frameworks

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.

2. Framework main features

Each major JavaScript framework has a different approach to updating the DOM, handling browser events, and providing an enjoyable developer experience. This article will explore the main features of "the big 4" frameworks, looking at how frameworks tend to work from a high level and the differences between them.

React tutorials
---------------

**Note:** React tutorials last tested in January 2023, with React/ReactDOM 18.2.0 and create-react-app 5.0.1.

If you need to check your code against our version, you can find a finished version of the sample React app code in our todo-react repository. For a running live version, see https://mdn.github.io/todo-react/.

1. Getting started with React

In this article we will say hello to React. We'll discover a little bit of detail about its background and use cases, set up a basic React toolchain on our local computer, and create and play with a simple starter app, learning a bit about how React works in the process.

2. Beginning our React todo list

Let's say that we've been tasked with creating a proof-of-concept in React – an app that allows users to add, edit, and delete tasks they want to work on, and also mark tasks as complete without deleting them. This article will walk you through putting the basic `App` component structure and styling in place, ready for individual component definition and interactivity, which we'll add later.

3. Componentizing our React app

At this point, our app is a monolith. Before we can make it do things, we need to break it apart into manageable, descriptive components. React doesn't have any hard rules for what is and isn't a component – that's up to you! In this article, we will show you a sensible way to break our app up into components.

4. React interactivity: Events and state

With our component plan worked out, it's now time to start updating our app from a completely static UI to one that actually allows us to interact and change things. In this article we'll do this, digging into events and state along the way.

5. React interactivity: Editing, filtering, conditional rendering

As we near the end of our React journey (for now at least), we'll add the finishing touches to the main areas of functionality in our Todo list app. This includes allowing you to edit existing tasks and filtering the list of tasks between all, completed, and incomplete tasks. We'll look at conditional UI rendering along the way.

6. Accessibility in React

In our final tutorial article, we'll focus on (pun intended) accessibility, including focus management in React, which can improve usability and reduce confusion for both keyboard-only and screen reader users.

7. React resources

Our final article provides you with a list of React resources that you can use to go further in your learning.

Ember tutorials
---------------

**Note:** Ember tutorials last tested in May 2020, with Ember/Ember CLI version 3.18.0.

If you need to check your code against our version, you can find a finished version of the sample Ember app code in the ember-todomvc-tutorial repository. For a running live version, see https://nullvoxpopuli.github.io/ember-todomvc-tutorial/ (this also includes a few additional features not covered in the tutorial).

1. Getting started with Ember

In our first Ember article we will look at how Ember works and what it's useful for, install the Ember toolchain locally, create a sample app, and then do some initial setup to get it ready for development.

2. Ember app structure and componentization

In this article we'll get right on with planning out the structure of our TodoMVC Ember app, adding in the HTML for it, and then breaking that HTML structure into components.

3. Ember interactivity: Events, classes and state

At this point we'll start adding some interactivity to our app, providing the ability to add and display new todo items. Along the way, we'll look at using events in Ember, creating component classes to contain JavaScript code to control interactive features, and setting up a service to keep track of the data state of our app.

4. Ember Interactivity: Footer functionality, conditional rendering

Now it's time to start tackling the footer functionality in our app. Here we'll get the todo counter to update to show the correct number of todos still to complete, and correctly apply styling to completed todos (i.e. where the checkbox has been checked). We'll also wire up our "Clear completed" button. Along the way, we'll learn about using conditional rendering in our templates.

5. Routing in Ember

In this article we learn about routing or URL-based filtering as it is sometimes referred to. We'll use it to provide a unique URL for each of the three todo views — "All", "Active", and "Completed".

6. Ember resources and troubleshooting

Our final Ember article provides you with a list of resources that you can use to go further in your learning, plus some useful troubleshooting and other information.

Vue tutorials
-------------

**Note:** Vue tutorial last tested in January 2023, with Vue 3.2.45.

If you need to check your code against our version, you can find a finished version of the sample Vue app code in our todo-vue repository. For a running live version, see https://mdn.github.io/todo-vue/.

1. Getting started with Vue

Now let's introduce Vue, the third of our frameworks. In this article, we'll look at a little bit of Vue background, learn how to install it and create a new project, study the high-level structure of the whole project and an individual component, see how to run the project locally, and get it prepared to start building our example.

2. Creating our first Vue component

Now it's time to dive deeper into Vue, and create our own custom component — we'll start by creating a component to represent each item in the todo list. Along the way, we'll learn about a few important concepts such as calling components inside other components, passing data to them via props and saving data state.

3. Rendering a list of Vue components

At this point we've got a fully working component; we're now ready to add multiple `ToDoItem` components to our app. In this article we'll look at adding a set of todo item data to our `App.vue` component, which we'll then loop through and display inside `ToDoItem` components using the `v-for` directive.

4. Adding a new todo form: Vue events, methods, and models

We now have sample data in place and a loop that takes each bit of data and renders it inside a `ToDoItem` in our app. What we really need next is the ability to allow our users to enter their own todo items into the app, and for that, we'll need a text `<input>`, an event to fire when the data is submitted, a method to fire upon submission to add the data and rerender the list, and a model to control the data. This is what we'll cover in this article.

5. Styling Vue components with CSS

The time has finally come to make our app look a bit nicer. In this article, we'll explore the different ways of styling Vue components with CSS.

6. Using Vue computed properties

In this article we'll add a counter that displays the number of completed todo items, using a feature of Vue called computed properties. These work similarly to methods but only re-run when one of their dependencies changes.

7. Vue conditional rendering: editing existing todos

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.

8. Focus management with Vue refs

We are nearly done with Vue. The last bit of functionality to look at is focus management, or put another way, how we can improve our app's keyboard accessibility. We'll look at using Vue refs to handle this — an advanced feature that allows you to have direct access to the underlying DOM nodes below the virtual DOM, or direct access from one component to the internal DOM structure of a child component.

9. Vue resources

Now we'll round off our study of Vue by giving you a list of resources that you can use to go further in your learning, plus some other useful tips.

Svelte tutorials
----------------

**Note:** Svelte tutorials last tested in August 2020, with Svelte 3.24.1.

If you need to check your code against our version, you can find a finished version of the sample Svelte app code as it should be after each article, in our mdn-svelte-tutorial repo. For a running live version, see our Svelte REPL at https://svelte.dev/repl/378dd79e0dfe4486a8f10823f3813190?version=3.23.2.

1. Getting started with Svelte

In this article we'll provide a quick introduction to the Svelte framework. We will see how Svelte works and what sets it apart from the rest of the frameworks and tools we've seen so far. Then we will learn how to set up our development environment, create a sample app, understand the structure of the project, and see how to run it locally and build it for production.

2. Starting our Svelte Todo list app

Now that we have a basic understanding of how things work in Svelte, we can start building our example app: a todo list. In this article we will first have a look at the desired functionality of our app, then we'll create a `Todos.svelte` component and put static markup and styles in place, leaving everything ready to start developing our To-Do list app features, which we'll go on to in subsequent articles.

3. Dynamic behavior in Svelte: working with variables and props

Now that we have our markup and styles ready we can start developing the required features for our Svelte To-Do list app. In this article we'll be using variables and props to make our app dynamic, allowing us to add and delete todos, mark them as complete, and filter them by status.

4. Componentizing our Svelte 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.

5. Advanced Svelte: Reactivity, lifecycle, accessibility

In this article we will add the app's final features and further componentize our app. We will learn how to deal with reactivity issues related to updating objects and arrays. To avoid common pitfalls, we'll have to dig a little deeper into Svelte's reactivity system. We'll also look at solving some accessibility focus issues, and more besides.

6. Working with Svelte stores

In this article we will show another way to handle state management in Svelte — Stores. Stores are global data repositories that hold values. Components can subscribe to stores and receive notifications when their values change.

7. TypeScript support in Svelte

We will now learn how to use TypeScript in Svelte applications. First we'll learn what TypeScript is and what benefits it can bring us. Then we'll see how to configure our project to work with TypeScript files. Finally we will go over our app and see what modifications we have to make to fully take advantage of TypeScript features.

8. Deployment and next steps

In this final article we will look at how to deploy your application and get it online, and also share some of the resources that you should go on to, to continue your Svelte learning journey.

Angular tutorials
-----------------

**Note:** Angular tutorials last tested in April 2021, with Angular CLI (NG) 11.2.5.

1. Getting started with Angular

In this article we look at what Angular has to offer, install the prerequisites and set up a sample app, and look at Angular's basic architecture.

2. Beginning our Angular todo list app

At this point, we are ready to start creating our to-do list application using Angular. The finished application will display a list of to-do items and includes editing, deleting, and adding features. In this article you will get to know your application structure, and work up to displaying a basic list of to-do items.

3. Styling our Angular app

Now that we've got our basic application structure set up and started displaying something useful, let's switch gears and spend an article looking at how Angular handles styling of applications.

4. Creating an item component

Components provide a way for you to organize your application. This article walks you through creating a component to handle the individual items in the list, and adding check, edit, and delete functionality. The Angular event model is covered here.

5. Filtering our to-do items

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.

6. Building Angular applications and further resources

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

Which frameworks did we choose?
-------------------------------

We are publishing our initial set of articles with guides focusing on five frameworks. Four of them are very popular and well-established — React/ReactDOM, Ember, Vue, and Angular — whereas Svelte is a comparative newcomer that shows a lot of promise and has gained a lot of recent popularity.

There is a variety of reasons for this:

* They are popular choices that will be around for a while — like with any software tool, it is good to stick with actively-developed choices that are likely to not be discontinued next week, and which will be desirable additions to your skill set when looking for a job.
* They have strong communities and good documentation. It is very important to be able to get help with learning a complex subject, especially when you are just starting out.
* We don't have the resources to cover *all* modern frameworks. That list would be very difficult to keep up-to-date anyway, as new ones appear all the time.
* As a beginner, trying to choose what to focus on out of the huge number of choices available is a very real problem. Keeping the list short is therefore helpful.

We want to say this upfront — we've **not** chosen the frameworks we are focusing on because we think they are the best, or because we endorse them in any way. We just think they score highly on the above criteria.

Note that we were hoping to have more frameworks included upon initial publication, but we decided to release the content and then add more framework guides later, rather than delay it longer. If your favorite framework is not represented in this content and you'd like to help change that, feel free to discuss it with us!


Adding a new todo form: Vue events, methods, and models - Learn web development

Adding a new todo form: Vue events, methods, and models
=======================================================

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

We now have sample data in place, and a loop that takes each bit of data and renders it inside a `ToDoItem` in our app. What we really need next is the ability to allow our users to enter their own todo items into the app, and for that we'll need a text `<input>`, an event to fire when the data is submitted, a method to fire upon submission to add the data and rerender the list, and a model to control the data. This is what we'll cover in this article.

|  |  |
| --- | --- |
| 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 about handling forms in Vue, and by association, events,
 models, and methods.
  |

Creating a New To-Do form
-------------------------

We now have an app that displays a list of to-do items. However, we can't update our list of items without manually changing our code! Let's fix that. Let's create a new component that will allow us to add a new to-do item.

1. In your components folder, create a new file called `ToDoForm.vue`.
2. Add a blank `<template>` and a `<script>` tag like before:

```html
<template></template>

<script>
 export default {};
</script>
```

3. Let's add in an HTML form that lets you enter a new todo item and submit it into the app. We need a `<form>` with a `<label>`, an `<input>`, and a `<button>`. Update your template as follows:

```html
<template>
  <form>
    <label for="new-todo-input"> What needs to be done? </label>
    <input
 type="text"
 id="new-todo-input"
 name="new-todo"
 autocomplete="off" />
    <button type="submit">Add</button>
  </form>
</template>
```

So we now have a form component into which we can enter the title of a new todo item (which will become a label for the corresponding `ToDoItem` when it is eventually rendered).
4. Let's load this component into our app. Go back to `App.vue` and add the following `import` statement just below the previous one, inside your `<script>` element:

```js
import ToDoForm from "./components/ToDoForm";
```

5. You also need to register the new component in your `App` component — update the `components` property of the component object so that it looks like this:

```js
components: {
  ToDoItem, ToDoForm,
}
```

6. Finally for this section, render your `ToDoForm` component inside your app by adding the `<to-do-form />` element inside your `App`'s `<template>`, like so:

```html
<template>
  <div id="app">
    <h1>My To-Do List</h1>
    <to-do-form></to-do-form>
    <ul>
      <li v-for="item in ToDoItems" :key="item.id">
        <to-do-item
 :label="item.label"
 :done="item.done"
 :id="item.id"></to-do-item>
      </li>
    </ul>
  </div>
</template>
```

Now when you view your running site, you should see the new form displayed.

![Our todo list app rendered with a text input to enter new todos](/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models/rendered-form-with-text-input.png)

If you fill it out and click the "Add" button, the page will post the form back to the server, but this isn't really what we want. What we actually want to do is run a method on the `submit` event that will add the new todo to the `ToDoItem` data list defined inside `App`. To do that, we'll need to add a method to the component instance.

Creating a method & binding it to an event with v-on
----------------------------------------------------

To make a method available to the `ToDoForm` component, we need to add it to the component object, and this is done inside a `methods` property to our component, which goes in the same place as `data()`, `props`, etc. The `methods` property holds any methods we might need to call in our component. When referenced, methods are fully run, so it's not a good idea to use them to display information inside the template. For displaying data that comes from calculations, you should use a `computed` property, which we'll cover later.

1. In this component, we need to add an `onSubmit()` method to a `methods` property inside the `ToDoForm` component object. We'll use this to handle the submit action.
 Add this like so:

```js
export default {
  methods: {
    onSubmit() {
      console.log("form submitted");
    },
  },
};
```

2. Next we need to bind the method to our `<form>` element's `submit` event handler. Much like how Vue uses the `v-bind` syntax for binding attributes, Vue has a special directive for event handling: `v-on`. The `v-on` directive works via the `v-on:event="method"` syntax. And much like `v-bind`, there's also a shorthand syntax: `@event="method"`.
 We'll use the shorthand syntax here for consistency. Add the `submit` handler to your `<form>` element like so:

```html
<form @submit="onSubmit">…</form>
```

3. When you run this, the app still posts the data to the server, causing a refresh. Since we're doing all of our processing on the client, there's no server to handle the postback. We also lose all local state on page refresh. To prevent the browser from posting to the server, we need to stop the event's default action while bubbling up through the page (`Event.preventDefault()`, in vanilla JavaScript). Vue has a special syntax called **event modifiers** that can handle this for us right in our template.
 Modifiers are appended to the end of an event with a dot like so: `@event.modifier`. Here is a list of event modifiers:
    * `.stop`: Stops the event from propagating. Equivalent to `Event.stopPropagation()` in regular JavaScript events.
    * `.prevent`: Prevents the event's default behavior. Equivalent to `Event.preventDefault()`.
    * `.self`: Triggers the handler only if the event was dispatched from this exact element.
    * `{.key}`: Triggers the event handler only via the specified key. MDN has a list of valid key values; multi-word keys just need to be converted to kebab-case (e.g. `page-down`).
    * `.native`: Listens for a native event on the root (outer-most wrapping) element on your component.
    * `.once`: Listens for the event until it's been triggered once, and then no more.
    * `.left`: Only triggers the handler via the left mouse button event.
    * `.right`: Only triggers the handler via the right mouse button event.
    * `.middle`: Only triggers the handler via the middle mouse button event.
    * `.passive`: Equivalent to using the `{ passive: true }` parameter when creating an event listener in vanilla JavaScript using `addEventListener()`.In this case, we need to use the `.prevent` modifier to stop the browser's default submit action. Add `.prevent` to the `@submit` handler in your template like so:

```html
<form @submit.prevent="onSubmit">…</form>
```

If you try submitting the form now, you'll notice that the page doesn't reload. If you open the console, you can see the results of the `console.log()` we added inside our `onSubmit()` method.

Binding data to inputs with v-model
-----------------------------------

Next up, we need a way to get the value from the form's `<input>` so we can add the new to-do item to our `ToDoItems` data list.

The first thing we need is a `data` property in our form to track the value of the to-do.

1. Add a `data()` method to our `ToDoForm` component object that returns a `label` field. We can set the initial value of the `label` to an empty string.
 Your component object should now look something like this:

```js
export default {
  methods: {
    onSubmit() {
      console.log("form submitted");
    },
  },
  data() {
    return {
      label: "",
    };
  },
};
```

2. We now need some way to attach the value of the `new-todo-input` element's field to the `label` field. Vue has a special directive for this: `v-model`. `v-model` binds to the data property you set on it and keeps it in sync with the `<input>`. `v-model` works across all the various input types, including checkboxes, radios, and select inputs. To use `v-model`, you add an attribute with the structure `v-model="variable"` to the `<input>`.
 So in our case, we would add it to our `new-todo-input` field as seen below. Do this now:

```html
<input
 type="text"
 id="new-todo-input"
 name="new-todo"
 autocomplete="off"
 v-model="label" />
```

**Note:** You can also sync data with `<input>` values through a combination of events and `v-bind` attributes. In fact, this is what `v-model` does behind the scenes. However, the exact event and attribute combination varies depending on input types and will take more code than just using the `v-model` shortcut.
3. Let's test out our use of `v-model` by logging the value of the data submitted in our `onSubmit()` method. In components, data attributes are accessed using the `this` keyword. So we access our `label` field using `this.label`.
 Update your `onSubmit()` method to look like this:

```js
methods: {
  onSubmit() {
    console.log('Label value: ', this.label);
  }
},
```

4. Now go back to your running app, add some text to the `<input>` field, and click the "Add" button. You should see the value you entered logged to your console, for example:
```

Label value: My value
```

Changing v-model behavior with modifiers
----------------------------------------

In a similar fashion to event modifiers, we can also add modifiers to change the behavior of `v-model`. In our case, there are two worth considering. The first, `.trim`, will remove whitespace from before or after the input. We can add the modifier to our `v-model` statement like so: `v-model.trim="label"`.

The second modifier we should consider is called `.lazy`. This modifier changes when `v-model` syncs the value for text inputs. As mentioned earlier, `v-model` syncing works by updating the variable using events. For text inputs, this sync happens using the `input` event. Often, this means that Vue is syncing the data after every keystroke. The `.lazy` modifier causes `v-model` to use the `change` event instead. This means that Vue will only sync data when the input loses focus or the form is submitted. For our purposes, this is much more reasonable since we only need the final data.

To use both the `.lazy` modifier and the `.trim` modifier together, we can chain them, e.g. `v-model.lazy.trim="label"`.

Update your `v-model` attribute to chain `lazy` and `trim` as shown above, and then test your app again. Try for example, submitting a value with whitespace at each end.

Passing data to parents with custom events
------------------------------------------

We now are very close to being able to add new to-do items to our list. The next thing we need to be able to do is pass the newly-created to-do item to our `App` component. To do that, we can have our `ToDoForm` emit a custom event that passes the data, and have `App` listen for it. This works very similarly to native events on HTML elements: a child component can emit an event which can be listened to via `v-on`.

In the `onSubmit` event handler of our `ToDoForm`, let's add a `todo-added` event. Custom events are emitted like this: `this.$emit("event-name")`. It's important to know that event handlers are case sensitive and cannot include spaces. Vue templates also get converted to lowercase, which means Vue templates cannot listen for events named with capital letters.

1. Replace the `console.log()` in the `onSubmit()` method with the following:

```js
this.$emit("todo-added");
```

2. Next, go back to `App.vue` and add a `methods` property to your component object containing an `addToDo()` method, as shown below. For now, this method can just log `To-do added` to the console.

```js
export default {
  name: "app",
  components: {
    ToDoItem,
    ToDoForm,
  },
  data() {
    return {
      ToDoItems: [
        { id: uniqueId("todo-"), label: "Learn Vue", done: false },
        {
          id: uniqueId("todo-"),
          label: "Create a Vue project with the CLI",
          done: true,
        },
        { id: uniqueId("todo-"), label: "Have fun", done: true },
        { id: uniqueId("todo-"), label: "Create a to-do list", done: false },
      ],
    };
  },
  methods: {
    addToDo() {
      console.log("To-do added");
    },
  },
};
```

3. Next, add an event listener for the `todo-added` event to the `<to-do-form></to-do-form>`, which calls the `addToDo()` method when the event fires. Using the `@` shorthand, the listener would look like this: `@todo-added="addToDo"`:

```html
<to-do-form @todo-added="addToDo"></to-do-form>
```

4. When you submit your `ToDoForm`, you should see the console log from the `addToDo()` method. This is good, but we're still not passing any data back into the `App.vue` component. We can do that by passing additional arguments to the `this.$emit()` function back in the `ToDoForm` component.
 In this case, when we fire the event we want to pass the `label` data along with it. This is done by including the data you want to pass as another parameter in the `$emit()` method: `this.$emit("todo-added", this.label)`. This is similar to how native JavaScript events include data, except custom Vue events include no event object by default. This means that the emitted event will directly match whatever object you submit. So in our case, our event object will just be a string.
 Update your `onSubmit()` method like so:

```js
onSubmit() {
  this.$emit('todo-added', this.label)
}
```

5. To actually pick up this data inside `App.vue`, we need to add a parameter to our `addToDo()` method that includes the `label` of the new to-do item.
 Go back to `App.vue` and update this now:

```js
methods: {
  addToDo(toDoLabel) {
    console.log('To-do added:', toDoLabel);
  }
}
```

If you test your form again, you'll see whatever text you enter logged in your console upon submission. Vue automatically passes the arguments after the event name in `this.$emit()` to your event handler.

Adding the new todo into our data
---------------------------------

Now that we have the data from `ToDoForm` available in `App.vue`, we need to add an item representing it to the `ToDoItems` array. This can be done by pushing a new to-do item object to the array containing our new data.

1. Update your `addToDo()` method like so:

```js
addToDo(toDoLabel) {
  this.ToDoItems.push({id:uniqueId('todo-'), label: toDoLabel, done: false});
}
```

2. Try testing your form again, and you should see new to-do items get appended to the end of the list.
3. Let's make a further improvement before we move on. If you submit the form while the input is empty, todo items with no text still get added to the list. To fix that, we can prevent the todo-added event from firing when name is empty. Since name is already being trimmed by the `.trim` modifier, we only need to test for the empty string.
 Go back to your `ToDoForm` component, and update the `onSubmit()` method like so. If the label value is empty, let's not emit the `todo-added` event.

```js
onSubmit() {
  if (this.label === "") {
    return;
  }
  this.$emit('todo-added', this.label);
}
```

4. Try your form again. Now you will not be able to add empty items to the to-do list.

![Our todo list app rendered with a text input to enter new todos](/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models/rendered-form-with-new-items.png)

Using v-model to update an input value
--------------------------------------

There's one more thing to fix in our `ToDoForm` component — after submitting, the `<input>` still contains the old value. But this is easy to fix — because we're using `v-model` to bind the data to the `<input>` in `ToDoForm`, if we set the name parameter to equal an empty string, the input will update as well.

Update your `ToDoForm` component's `onSubmit()` method to this:

```js
onSubmit() {
  if (this.label === "") {
    return;
  }
  this.$emit('todo-added', this.label);
  this.label = "";
}
```

Now when you click the "Add" button, the "new-todo-input" will clear itself.

Summary
-------

Excellent. We can now add todo items to our form! Our app is now starting to feel interactive, but one issue is that we've completely ignored its look and feel up to now. In the next article, we'll concentrate on fixing this, looking at the different ways Vue provides to style components.

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