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.
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.
Predict and Run 10 min · Investigate 15 min · Modify 10 min · Make 15 min
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).
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.
| What you will see | A question to ask | The 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. |
One possible solution for each task. Other correct programs are fine.
<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>
<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>
<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: 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.
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.
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.