Run a function of your own when something is clicked, join a box to data with v-model, and change a ref's .value in the script.
Every sign-up form, search box and Add button is an event and some data. Vue joins them up for you.
Two new pieces join the page to the data.
Events: @click="addPlayer" runs a function when the button is clicked. The function lives in setup and is returned like the data:
function addPlayer() {
players.value.push(newName.value);
newName.value = "";
}
return { players, newName, addPlayer };
Inputs: v-model="newName" joins a box to a ref, both ways: typing changes the data, and changing the data changes the box. No .value of the box and no "input" event, as in the DOM course.
The hard part: on the page you write newName; in the script you write newName.value. A ref is a box, and in the script you open it yourself.
Make your prediction first. Help opens once you've locked it in.
<div id="app">
<input v-model="name">
<p>Hello, {{ name }}!</p>
</div>
<script src="vue.js"></script>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const name = ref("friend");
return { name };
}
}).mount("#app");
</script>
There is no event and no .value here, only v-model.
Press Run, type a name and press Add. Then press Add with the box empty: nothing happens, because of the if.
<div id="app">
<h1>Chess team</h1>
<input v-model="newName" placeholder="A name">
<button @click="addPlayer">Add</button>
<p>Adding: {{ newName }}</p>
<ul>
<li v-for="name in players">{{ name }}</li>
</ul>
</div>
<script src="vue.js"></script>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const players = ref(["Ada", "Sam"]);
const newName = ref("");
function addPlayer() {
if (newName.value !== "") {
players.value.push(newName.value);
newName.value = "";
}
}
return { players, newName, addPlayer };
}
}).mount("#app");
</script>
<div id="app">
<h1>Chess team</h1>
<input v-model="newName" placeholder="A name">
<button @click="addPlayer">Add</button>
<p>Adding: {{ newName }}</p>
<ul>
<li v-for="name in players">{{ name }}</li>
</ul>
</div>
<script src="vue.js"></script>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const players = ref(["Ada", "Sam"]);
const newName = ref("");
function addPlayer() {
if (newName.value !== "") {
players.value.push(newName.value);
newName.value = "";
}
}
return { players, newName, addPlayer };
}
}).mount("#app");
</script>
Box, button and function.
The page and the script.
The score will not change.
Match each part with what it does.
Clicking Add a point shows a red error, and the score stays at 0. Click the line that is wrong.
A function of your own.
A function in setup, returned, and a button that names it.
function reset() { players.value = ["Ada", "Sam"]; newName.value = ""; } then add reset to the return, and <button @click="reset">Reset</button>.

A second box.
A new box needs a new ref, returned, and v-model on the box.
const club = ref("Chess");, club in the return, <input v-model="club">, and {{ club }} in the heading.

Add a Reset button that puts the list back to Ada and Sam.
This ticks when your page has all of the above.
Add a box for the club's name, and show it in the heading.
This ticks when your page has all of the above.
Make a name badge: boxes for a name and a role joined with v-model, the badge shown with {{ }} in a bordered box, and a button that runs a function (make the name shout in capitals with toUpperCase(), or swap the two).
Make boxes with v-model, show them on a badge, and add a button that runs a function of your own.
This ticks when your page has all of the above.
Next: values worked out from data, with computed.
Students predict that v-model follows each letter, add names with a function, match the parts, find score++ on a ref, add a Reset function and a second box, and make a badge maker. About 55 minutes.
Open the teacher guide: answers, solutions, slides and a worksheet.
Read the unit primer first. Two new pieces. @click="addPlayer" names a function to run on a click; the function is written in setup and returned with the data. v-model="newName" joins a box to a ref both ways: typing changes the ref, and setting the ref (to empty text, say) changes the box. Compare the DOM course, where students read box.value and listened for the "input" event themselves.
The hard part of the whole course: a ref is a box. On the page Vue opens it for you ({{ score }}, @click="score++"); in the script you open it yourself (score.value++). Writing score++ in a function gives a red error, "Assignment to constant variable", because the ref was made with const. The playground's hint names .value for this case. Expect it all lesson; it is also the planted bug.
Students mix up when to write .value. Ask "are you on the page or in the script?" every time, and let them answer before they type.
Stretch: Add when Enter is pressed: @keyup.enter="addPlayer" on the box. Remove a player when their name is clicked (pass the name to a function).
Support: Give the Reset function written out; students return it and add the button.
Next lesson: computed values, worked out from data and kept up to date. Class idea: find an Add button on a real site and say which data it changes.