Categories
Vue 3

Vue 3 — Custom Events

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to emit and handle custom events with Vue 3.

Custom Events

We can emit custom events with the this.$emit method.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <component-a @increment-count="count++"></component-a>
      <p>{{count}}</p>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            count: 0
          };
        }
      });

      app.component("component-a", {
        template: `
          <div>
            <button @click='this.$emit("increment-count")'>click      me</button>
          </div>`
      });

      app.mount("#app");
    </script>
  </body>
</html>

We emit the increment-count event with the from component-a .

Then we listen to the same event within the parent Vue instance’s template with:

<component-a @increment-count="count++"></component-a>

The case of the event names have to be the same for this to work.

Therefore, when we click on the ‘click me’ button, we can increase the count by 1.

Defining Custom Events

We can define custom events with the emits option of a component.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <component-a @increment-count="count++"></component-a>
      <p>{{count}}</p>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            count: 0
          };
        }
      });

      app.component("component-a", {
        emits: ["increment-count"],
        template: `
          <div>
            <button @click='$emit("increment-count")'>click me</button>
          </div>`
      });

      app.mount("#app");
    </script>
  </body>
</html>

We have the emits option which has an array of event name strings that component-a can emit.

This serves as better documentation for our components since we can restrict the kinds of events that can be emitted.

Validate Emitted Events

We can add code to validate emitted events.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <component-a @increment-count="count += $event"></component-a>
      <p>{{count}}</p>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            count: 0
          };
        }
      });

      app.component("component-a", {
        emits: {
          ["increment-count"](value) {
            return value === 2;
          }
        },
        template: `
          <div>
            <button @click='$emit("increment-count", 2)'>click me</button>
          </div>`
      });

app.mount("#app");
    </script>
  </body>
</html>

to make sure that we always pass 2 into the $emit method.

We have the emits property in our component-a object with the increment-count method.

It takes the value parameter, which is the value that we passed in as the 2nd argument.

In the method, we return the validation result as a boolean.

If it’s valid, we return true .

Otherwise, we return false .

v-model arguments

v-model arguments can also be validated.

We can check the prop value with the props property.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <component-a v-model:foo="bar"></component-a>
      <p>{{bar}}</p>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            bar: ""
          };
        }
      });

      app.component("component-a", {
        props: {
          foo: String
        },
        template: `
          <input
            type="text"
            :value="foo"
            @input="$emit('update:foo', $event.target.value)">
        `
      });

      app.mount("#app");
    </script>
  </body>
</html>

We have the props property, that has the key foo .

The value is String , so foo has to be a string.

Our input emits the update:foo event so we send the inputted value back to the parent component.

Then we can bind the parent’s property with the v-model:foo directive so that we can synchronize the value of foo with the value of the bar state.

Therefore, when we type into the input box, we’ll see the value that we entered displayed.

Conclusion

We can emit custom events by calling this.$emit with an event name and an optional 2nd argument with the value.

Then we can listen to it with the @ directive shorthand.

Categories
Vue 3

Vue 3 — v-model Modifiers and Components

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to use the Vue 3 v-model directive and create simple Vue 3 components.

Select Options

Select option values can be objects.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <select v-model="selected">
        <option :value="{ fruiit: 'apple' }">apple</option>
        <option :value="{ fruiit: 'orange' }">orange</option>
        <option :value="{ fruiit: 'grape' }">grape</option>
      </select>
      <p>{{ selected }}</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return { selected: {} };
        }
      }).mount("#app");
    </script>
  </body>
</html>

to create a select dropdown that has option values bound to objects.

:value accepts an object.

So when we select a value, we’ll see that selected would also be an object.

This is because we set v-model ‘s value to selected .

v-model Modifiers

v-model can take various modifiers.

.lazy

The .lazy modifier makes v-model sync with the Vue instance state after each change event.

By default, v-model syncs with the state after each input event is emitted.

We can use that by writing:

<input v-model.lazy="msg" />

.number

The .number modifier lets us convert whatever is entered to a number automatically.

For instance, we can write:

<input v-model.number="numApples" type="number" />

to convert numApples to a number automatically.

By default, an HTML input’s value is always a string, so this is a useful shorthand.

If the value can’t be parsed with parseFloat , then the original value is returned.

.trim

The .trim modifier automatically trims whitespace from user inputs.

We can use it by writing:

<input v-model.trim="msg" />

v-model with Components

v-model can be used with components as long as it emits an input event and takes in a value prop to populate the form control’s value.

This lets us make custom form control components easily.

Components Basics

We can create Vue components with the app.component method.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <button-counter />
    </div>
    <script>
      const app = Vue.createApp({});

      app.component("button-counter", {
        data() {
          return {
            count: 0
          };
        },
        template: `
          <div>
            <button @click="count++">
              increment
            </button>
            <p>{{ count }}</p>
          </div>
        `
      });

      app.mount("#app");
    </script>
  </body>
</html>

to create a component and then use it in our app.

We called app.component to with the component name as the first argument.

We called our component 'button-counter' .

The 2nd argument has the component object with the template and logic.

data returns the initial state object.

And template has the template string with the elements we want to display.

Inside it, we increment the count when a button is clicked and display the count .

Then we use the button-counter component in our app by adding the HTML for it.

Now we should see the increment button and the count value update as we click it.

Conclusion

v-model works with select options and components.

We can create simple components with the app.component method.

Categories
Vue 3

Vue 3 — v-model

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to use the Vue 3 v-model directive.

Multiline Text

v-model also works with multiline text.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <textarea v-model="message" placeholder="message"></textarea>
      <p style="white-space: pre-line;">{{ message }}</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            message: ""
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

And when we type in multiple lines of text, it’ll be displayed with the same formatting.

This is because we have the white-space: pre-line; style.

We shouldn’t use interpolation for text areas.

Instead, we always use v-model .

Checkbox

v-model also works with checkboxes.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <input type="checkbox" v-model="checked" />
      <label for="checkbox">{{ checked }}</label>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            checked: true
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

to bind the checked value of the checkbox to the checked state.

We can also have multiple checkboxes bound to the same array:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <input type="checkbox" value="apple" v-model="checkedFruits" />
      <label>apple</label>
      <input type="checkbox" value="orange" v-model="checkedFruits" />
      <label>orange</label>
      <input type="checkbox" value="grape" v-model="checkedFruits" />
      <label>grape</label>
      <p>{{checkedFruits}}</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            checkedFruits: []
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

v-model is smart enough to populate the checkedFruits array with the checked choices.

All we have to do is set the value attribute value and the array variable to bind to v-model and we’re set.

Now when we check or uncheck the checkboxes, the checkedFruits array will change automatically.

Radio

Like checkboxes, Vue 3’s v-model directive can bind to radio button choices.

All we need to have is the value attribute and the v-model directive on each checkbox and Vue will do the selection binding automatically.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <input type="radio" value="apple" v-model="selected" />
      <label>apple</label>
      <input type="radio" value="orange" v-model="selected" />
      <label>orange</label>
      <input type="radio" value="grape" v-model="selected" />
      <label>grape</label>
      <p>{{selected}}</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            selected: ""
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

We pass in the selected property returned from data as the value of the v-model directive.

The value attribute as the value of each radio button.

Now when we click on the radio button, we’ll see the value displayed below it.

We can only click one since they’re all bound to the same variable.

Select

v-model also works with select elements.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <select v-model="selected">
        <option disabled value="">Please select one</option>
        <option>apple</option>
        <option>orange</option>
        <option>grape</option>
      </select>
      <p>{{ selected }}</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            selected: ""
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

We passed the selected value to the v-model so it’ll be updated if we select a value.

If there’s no value attribute in the option, then the text between the option tags will be used as the value.

Conclusion

v-model lets us bind various form control values to Vue instance states.

Categories
Vue 3

Vue 3 — More About v-model

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to use the Vue 3 v-model directive.

Multiple Select

Select elements that let us do multiple selections work with the v-model directive.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <select v-model="selected" multiple>
        <option disabled value="">Please select one</option>
        <option>apple</option>
        <option>orange</option>
        <option>grape</option>
      </select>
      <p>{{ selected }}</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            selected: []
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

We have the select element which has the multiple attribute.

The selected variable is a variable instead of a string since it can contain multiple values.

v-model is bound to the selected array so that Vue can get all the selected values and put it in the array.

Now when we choose multiple options from the select box, we can see all of them in an array.

Dynamic Options

We can add dynamic options in the select element.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <select v-model="selected">
        <option disabled value="">Please select one</option>
        <option v-for="option in options" :value="option.value">
          {{ option.text }}
        </option>
      </select>
      <p>{{ selected }}</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            selected: [],
            options: [
              { value: "apple", text: "apple" },
              { value: "orange", text: "orange" },
              { value: "grape", text: "grape" }
            ]
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

to render the options with the v-for directive.

option.value is used as the value of each option .

and option.text is used as the value of each text entry.

Value Bindings

Radio buttons and select elements are bound to string with v-model .

Checkboxes are bound to boolean values.

We can use the v-bind directive to bind to types of values that are different from the default.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <input
        type="checkbox"
        v-model="toggle"
        true-value="yes"
        false-value="no"
      />
      <p>{{ toggle }}</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return {
            toggle: ""
          };
        }
      }).mount("#app");
    </script>
  </body>
</html>

We added the true-value and false-value props so that the checkbox bind to those values instead of a boolean.

So true is 'yes' and false is 'no' .

That’s what we’ll see when we click the checkbox.

We can do the same thing with radio buttons.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <input type="radio" v-model="selected" :value="apple" />
      <label>apple</label>
      <input type="radio" v-model="selected" :value="orange" />
      <label>orange</label>
      <p>{{ selected }}</p>
    </div>
    <script>
      const vm = Vue.createApp({
        data() {
          return { selected: "", apple: "apple", orange: "orange" };
        }
      }).mount("#app");
    </script>
  </body>
</html>

We dynamically bound the value with the :value directive instead of setting the value statically.

Since v-model of both radio buttons are set to the same value, we can select between them.

Then their value will be displayed.

Conclusion

Many kinds of form controls work with the v-model directive.

Also, we can bind to their values in different ways.

Categories
Vue 3

Vue 3 — Keyboard and Mouse

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to handle key and mouse events in Vue 3 components.

Key Modifiers

Vue 3 can handle keyboard events.

For instance, we can write:

<input @keyup.enter="submit" />

to run the submit method when the keyup event is triggered by pressing the enter key.

Any valid key name is acceptable as the modifier.

The following key aliases can also be used as modifiers:

  • .enter
  • .tab
  • .delete (captures both "Delete" and "Backspace" keys)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

System Modifier Keys

We can also add modifiers for system modifier keys like Alt and Ctrl.

We can use the following as modifiers:

  • .ctrl
  • .alt
  • .shift
  • .meta

The meta key is the Windows key on Windows keyboards.

On Sun keyboards, it’s the diamond key.

And on Macs, it’s the command key.

So we can listen to the Ctrl + Enter key combo press on an element by writing:

<input @keyup.ctrl.enter="clear" />

We can also listen to Ctrl + click by writing:

<div @click.ctrl="onCtrlClick">ctrl + click me</div>

.exact Modifier

The .exact modifier lets us control the exact combination of system modifiers needed to trigger an event.

For example, if we have:

<button @click.ctrl="onClick">click me</button>

then if alt or shift is pressed, then onClick will also be run.

However, if we have:

<button @click.ctrl.exact="onCtrlClick">A</button>

Then onCtrlClick only runs when we Ctrl + click the button.

Mouse Button Modifiers

Vue 3 also provides modifiers for mouse buttons.

They are:

  • .left
  • .right
  • .middle

for listening to the presses of specific buttons.

Listeners in HTML

Listeners in HTML frees the component code including DOM logic, which is cleaner than having them all in JavaScript.

When the view model is destroyed, all event listeners are automatically removed.

Form Input Bindings

We can use the v-model directive to bind the input value to the state property.

It’s syntactic sugar for updating data on user input events.

v-model ignores the initial value , checked , or selected attributes found in any element.

Only the state in the Vue instances is treated as the source of truth.

Therefore, we should remove those attributes and just set the initial value in the Vue instance.

v-model internally uses different properties and emit different events for different input elements.

Text inputs use value property and input event.

Checkboxes and radio buttons use the checked property and change event.

Select fields use the value as a prop and change as an event.

To use the v-model directive, we can write:

<!DOCTYPE html>  
<html lang="en">  
  <head>  
    <title>App</title>  
    <script src="https://unpkg.com/vue@next"></script>  
  </head>  
  <body>  
    <div id="app">  
      <input v-model="message" placeholder="message" />  
      <p>{{ message }}</p>  
    </div>  
    <script>  
      const vm = Vue.createApp({  
        data() {  
          return {  
            message: ""  
          };  
        }  
      }).mount("#app");  
    </script>  
  </body>  
</html>

We returned an object with the message property so that we can use it with v-model .

Then we render the value of message to show what we entered.

v-model will automatically synchronize the input value and the value of message .

Therefore, when we type something in the box, it’ll be displayed below it.

Conclusion

We can listen to key and mouse events with v-on .

v-model binds the inputted value to the Vue instance state.