← Teacher guide

Events and inputs

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.

Apps with Vue · Data on the page · about 55 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 15 min · Make 15 min

Before class

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.

Running the lesson

  1. Predict: ask what DOM-course students would have needed (an input event and box.value).
  2. Run: press Add with an empty box and ask which line stops it.
  3. Investigate: before the bug, ask students to underline every .value in the script and none on the page.
  4. Modify: a new function is three edits: write it, return it, name it in @click.
  5. Make: ask which ref each box changes, and what the button's function changes.

The hard part (on purpose)

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.

When students get stuck

What you will seeA question to askThe fix
A red error: Assignment to constant variable.Is that a ref, changed in the script?Change its .value: score.value++.
Clicking does nothing; the console warns a property is not defined.Is the function in the return?return { players, newName, addPlayer, reset };
The box and the paragraph do not match.Does v-model name the same ref the paragraph shows?Use the same name in v-model and in {{ }}.

Answers to the checks

  1. Predict: You clear the box and type Kai. What does the paragraph show while you type?
    It changes with every letter. v-model puts what you type into name straight away, and {{ name }} shows it.
  2. Which part does what?: Match each part with what it does.
    v-model="newName" → D. joins the box and newName, both ways; @click="addPlayer" → B. runs addPlayer when the button is clicked; players.value.push(newName.value); → C. adds the typed name to the list; newName.value = ""; → E. empties the data, and so the box; return { players, newName, addPlayer }; → A. lets the page use the data and the function
    Setting newName.value to empty text also empties the box: v-model works in both directions.
  3. Two ways to write it: Why does the function write newName.value, but the page writes newName?
    The page opens refs for you; in the script you open them yourself with .value
    newName is a ref, a box Vue watches. The page unwraps it for you; the script reaches the value inside with .value.
  4. Spot the bug: Clicking Add a point shows a red error, and the score stays at 0. Click the line that is wrong.
    line 13
    score is a ref, made with const. score++ tries to change the box itself. The number is score.value, so write score.value++.
  5. Where this leads: Your page should show how many players there are, and say Team full at 5. Where should the count come from?
    Worked out from the list, so it is always right
    A value worked out from other data should be worked out again whenever that data changes. Next: computed.

Solutions

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

Modify › Reset

<div id="app">
  <h1>Chess team</h1>
  <input v-model="newName" placeholder="A name">
  <button @click="addPlayer">Add</button>
  <button @click="reset">Reset</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 = "";
        }
      }
      function reset() {
        players.value = ["Ada", "Sam"];
        newName.value = "";
      }
      return { players, newName, addPlayer, reset };
    }
  }).mount("#app");
</script>

Modify › The club's name

<div id="app">
  <h1>{{ club }} team</h1>
  <input v-model="club" placeholder="Club name">
  <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 club = ref("Chess");
      const players = ref(["Ada", "Sam"]);
      const newName = ref("");
      function addPlayer() {
        if (newName.value !== "") {
          players.value.push(newName.value);
          newName.value = "";
        }
      }
      return { club, players, newName, addPlayer };
    }
  }).mount("#app");
</script>

a badge maker

<div id="app">
  <h1>Badge maker</h1>
  <input v-model="person" placeholder="Your name">
  <input v-model="role" placeholder="Your role">
  <button @click="shout">Make it loud</button>
  <div style="border: 3px solid teal; padding: 12px; margin-top: 12px;">
    <h2>{{ person }}</h2>
    <p>{{ role }}</p>
  </div>
</div>

<script src="vue.js"></script>
<script>
  const { createApp, ref } = Vue;
  createApp({
    setup() {
      const person = ref("Ada");
      const role = ref("Captain");
      function shout() {
        person.value = person.value.toUpperCase() + "!";
      }
      return { person, role, shout };
    }
  }).mount("#app");
</script>

Stretch and support

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.

Exit ticket

In a Vue function, how do you add 1 to a ref called score, and why is it different on the page?

score.value++; the page unwraps refs for you, but the script reaches the value inside with .value.

What each step is for

Where it leads

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.

Sources