← Teacher guide

Lists and choices: v-for and v-if

Students predict that pushing to a list adds a tag, trace the page as the list changes, find v-for on the wrong tag, add a Clear button and a Team full message, and make a playlist.

Apps with Vue · Data on the page · about 50 minutes · Open the student lesson

Classroom resources

Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.

Students will be able to

Timing

Predict and Run 10 min · Investigate 15 min · Modify 10 min · Make 15 min

Before class

Read the unit primer first. v-for="name in players" on a tag makes one copy of that tag per item; inside it, name is the item for that copy. v-if="…" adds the tag while the condition is true and removes it otherwise. Both are attributes on the tag they control, which is why the planted bug (v-for on the ul) makes three lists.

This reverses the DOM course's lesson on lists, where changing an array did not change the page ("list-is-live"). In Vue it does, because the list is a ref. Say so explicitly to students who did the DOM course; it is a good moment to name what Vue is doing for them.

Real Vue code adds :key to v-for tags (:key="name") so Vue can tell items apart when they move; it does not change what students see here, so the course leaves it to the stretch. players = [] inside @click works because the page unwraps refs for you (lesson 3 shows the script side).

Running the lesson

  1. Predict: ask DOM-course students what happened when they pushed to an array there.
  2. Run: empty the list and ask what made the message appear.
  3. Investigate: do the trace on paper first, then check it by clicking.
  4. Modify: for Team full, ask which number to compare and with which sign.
  5. Make: ask each student to say which tag v-for repeats.

The hard part (on purpose)

Students put v-for on the container because "it's the list". Ask "which tag do you want more of?" and let them move it themselves.

When students get stuck

What you will seeA question to askThe fix
Several lists, each with one item.Which tag has the v-for?Put v-for on the li, not the ul or ol.
The message never shows or never goes.What does the v-if compare, and is it === ?v-if="players.length === 0"; a single = sets a value instead of comparing.
The names show as {{ name }}.Is the li inside the div with id app?Keep everything Vue should handle inside #app.

Answers to the checks

  1. Predict: You click Add Kai once. How many names are on the page?
    4. push adds Kai to players, and v-for makes an li for every item, so a fourth li appears.
  2. Trace the page: Start with Ada, Sam and Lin. Fill in the page after each click.
    4, no, 0, yes, 1, no
    The page always matches the list: one li per item, and the message only while the list is empty.
  3. Which part does what?: Match each part with what it does.
    v-for="name in players" → A. makes this tag once for each item; {{ name }} → C. the item for this copy of the tag; v-if="players.length === 0" → D. shows this tag only while the list is empty; players.push('Kai') → B. adds an item to the end of the list
    v-for and v-if go on the tag they control. The data decides how many copies there are and whether the tag shows.
  4. Spot the bug: The page shows three separate lists, each with one name. There is no error. Click the line that is wrong.
    line 2
    v-for repeats the tag it is written on. On the ul, it makes three lists. Put it on the li: one list, three items.
  5. Where this leads: Your team page should add whatever name someone types, not always Kai. What does it need?
    A box joined to some data, and a function that adds it
    Next lesson: v-model joins a box to data, and a function in setup does the adding.

Solutions

One possible solution for each task. Other correct programs are fine.

Modify › Clear the list

<div id="app">
  <h1>Chess team</h1>
  <ul>
    <li v-for="name in players">{{ name }}</li>
  </ul>
  <p v-if="players.length === 0">No players yet.</p>
  <button @click="players.push('Kai')">Add Kai</button>
  <button @click="players.pop()">Remove the last</button>
  <button @click="players = []">Clear</button>
</div>

<script src="vue.js"></script>
<script>
  const { createApp, ref } = Vue;
  createApp({
    setup() {
      const players = ref(["Ada", "Sam", "Lin"]);
      return { players };
    }
  }).mount("#app");
</script>

Modify › Team full

<div id="app">
  <h1>Chess team</h1>
  <ul>
    <li v-for="name in players">{{ name }}</li>
  </ul>
  <p v-if="players.length === 0">No players yet.</p>
  <p v-if="players.length >= 5">Team full!</p>
  <button @click="players.push('Kai')">Add Kai</button>
  <button @click="players.pop()">Remove the last</button>
</div>

<script src="vue.js"></script>
<script>
  const { createApp, ref } = Vue;
  createApp({
    setup() {
      const players = ref(["Ada", "Sam", "Lin"]);
      return { players };
    }
  }).mount("#app");
</script>

a playlist

<div id="app">
  <h1>My playlist</h1>
  <ol>
    <li v-for="song in songs">{{ song }}</li>
  </ol>
  <p v-if="songs.length === 0">Nothing to play.</p>
  <button @click="songs.push('Another song')">Add a song</button>
  <button @click="songs.shift()">Play the first</button>
</div>

<script src="vue.js"></script>
<script>
  const { createApp, ref } = Vue;
  createApp({
    setup() {
      const songs = ref(["First song", "Second song"]);
      return { songs };
    }
  }).mount("#app");
</script>

Stretch and support

Stretch: Add :key="song" to the v-for. Number the items with v-for="(song, i) in songs" and {{ i + 1 }}. Add v-else after a v-if.

Support: Give the ul with v-for already written; students add only the v-if message.

Exit ticket

Why does v-for go on the li and not the ul?

v-for repeats the tag it is on, once per item; we want many li tags in one list, not many lists.

What each step is for

Where it leads

Next lesson: functions for events and v-model for inputs, so the list can take any name. Class idea: find three lists on a website and say what each item's data would be.

Sources