Chapter 4. Forms and inputs

This chapter covers

  • Binding values to the DOM
  • Using text binding
  • Modifiers

Our application has evolved substantially since chapter 1. We’ve created items and allowed users to add items to a cart. We now need a way for our customers to check out and enter their information. Let’s add input forms to our application so the customer can enter their address and billing information into the app. Then we need to save this information in our app for later use.

To accomplish our goal, we must bind the form data to our model in our application. The v-model directive was made for this use case.

Definition

The v-model directive creates a two-way data binding between form or text area inputs and the template. This assures data in our application model will always be in sync with our UI.

Two-way data binding vs. one-way data binding

In practice, two-way data binding (figure 4.1) may, or may not, be the best solution. In certain instances, data will never need to change after it’s captured from user input. Other frameworks and libraries such as React and Angular 2 have chosen one-way data bindings by default. Angular 1 started with two-way binding and dropped it for performance management reasons when building Angular 2. One-way data binding occurs when data captured isn’t synced from the model to the view when the input changes. Additional logic needs to be added for the values to change in the model or view. Ember.js decided to stick with two-way data binding by default. With the v-model directive, the data is bound two ways. Regardless, we can specify a property as one-way bound in Vue using the v-once directive.

Figure 4.1. The model updates the view while the view updates the model.

The v-once directive renders an element or component once only. On any additional re-renders, the element or component will be treated as static content and skipped. To learn more about the v-once directive, check out the official API documentation at https://vuejs.org/v2/api/#v-once.

Later in the book we’ll discuss component properties and how they can be passed to other components. These properties form a one-way-down binding between the parent property and the child one. This will become useful in the future.

The v-model directive was made to work with all sorts of form inputs, including text boxes, text areas, check boxes, radio buttons, and select drop-down controls. We’ll need all these elements to build our new checkout form. Let’s look at using the v-model directive and how it works with binding inputs.

4.1. Using v-model binding

Model binding in our applications will help us update data on our user inputs with our template. In our application, we’ve worked primarily with the Vue data object to display static information. Interaction with the application has been limited to a few button-click events. We need to add a way for users to fill in their shipping information at checkout. To keep track of the form inputs, we’ll use the v-model directive and basic input bindings to add more reactivity to the application.

Before we begin, you might be wondering what the differences are between the v-model directive and the v-bind directive that we used in chapter 2. Keep in mind that the v-model directive is used mainly for input and form binding. We’ll use the v-model directive in this chapter to bind our text inputs for our checkout page. The v-bind directive is mostly used to bind HTML attributes. We could use v-bind on an src attribute on an <img> tag or bind it to the class attribute on a <div> tag for example. Both are useful, yet they’re used in different situations. We’ll look at the v-bind directive in more detail later in the chapter.

It’s worth mentioning that the v-model directive uses the v-bind directive behind the scenes. Let’s say you had <input v-model="something">. The v-model directive is syntactic sugar for <input v-bind:"something" v-on: input="something=$event.target.value">. Regardless, using the v-model directive is much easier to type and understand.

In figure 4.2 we see how the v-model directive is broken down. It is added to the input and creates a two-way data bound object.

Figure 4.2. Up close with the v-model directive

To begin, we’ll need to add new HTML to our application. Open the index.html page that you created in the last two chapters and look for the v-else directive (or you can download the supplied index.html file for chapter 3). Inside this <div> tag we’ll add the HTML code in this chapter. In chapter 7 we’ll discuss a better way of breaking up our application into components. For now, we’ll use the simple v-if directive as a toggle to display our checkout page.

As with the previous chapters, each code snippet is split into its own file. Please combine this with the index.html to create a completed application.

Listing 4.1. A v-model directive with first and last name inputs: chapter-04/first-last.html
<div class="col-md-6">
  <strong>First Name:</strong>
  <input v-model="order.firstName"        1
    class="form-control"/>
</div>
<div class="col-md-6">
  <strong>Last Name:</strong>
  <input v-model="order.lastName"
   class="form-control"/>  //#A
</div>
<div class="col-md-12 verify">
  <pre>
    First Name: {{order.firstName}}       2
    Last Name:  {{order.lastName}}        2
  </pre>
</div>

  • 1 The firstName and lastName are bound using v-model.
  • 2 The firstName and lastName properties are displayed in real time as values change in input.

The code creates two text boxes for the first and last name and each text box is bound to a property that’s synced in real time. These properties are created in the data object. To make this easier, we’ll use an order property to keep these values saved in our Vue instance data object. This will be added to the index.html file.

In the data object, we’ll need to add our new order property. We need this order property so we can keep track of the first and last names. Add the following code to the existing index.html data object that we used from the previous chapter.

Listing 4.2. The Vue instance data object order property: chapter-04/data-property.js
data: {
  sitename: 'Vue.js Pet Depot',
  showProduct: true,
  order: {
    firstName: '',
    lastName: ''
  },

The order object in this listing is in the data object inside the Vue constructor. We can reference this object throughout our code using the double curly brace Mustache syntax {{}} that we learned about in chapter 2. For example, {{order.firstName}} will be replaced by the firstName from the order object. Keeping our order information in an object makes it easier to understand where the data is in the future.

It’s worth mentioning that we could use an empty order object here and not define the properties firstName and lastName explicitly inside it. Vue.js can implicitly add the properties to the object. For the sake of simplicity, and to keep the code base a little cleaner, we’ll add the properties so we can see how everything works.

After typing data into our checkout form, notice that values appear in real time in the box (figure 4.3). This is the beauty of two-way data binding. Values are automatically synced to each other without any other logic needed.

Figure 4.3. Text is updated in real time into the box at the bottom.

We now have the start of our checkout page. Let’s add more form inputs to our index.html file so our customer can add in their address information, as shown next. We can add this HTML after the HTML code that we added in listing 4.1.

Listing 4.3. Adding in our other text inputs and select box: chapter-04/text-input.html
<div class="form-group">
  <div class="col-md-12"><strong>Address:</strong></div>
  <div class="col-md-12">
    <input v-model="order.address"                        1
      class="form-control" />
  </div>
</div>
<div class="form-group">
  <div class="col-md-12"><strong>City:</strong></div>
  <div class="col-md-12">
    <input v-model="order.city"                           1
      class="form-control" />
  </div>
</div>
<div class="form-group">
  <div class="col-md-2">
  <strong>State:</strong>
    <select v-model="order.state"                         2
      class="form-control">
      <option disabled value="">State</option>
      <option>AL</option>
      <option>AR</option>
      <option>CA</option>
      <option>NV</option>
    </select>
  </div>
</div>
<div class="form-group">
  <div class="col-md-6 col-md-offset-4">
  <strong>Zip / Postal Code:</strong>

    <input v-model="order.zip"                            1
      class="form-control"/>
  </div>
</div>
<div class="col-md-12 verify">
  <pre>                                                   3
    First Name: {{order.firstName}}
     Last Name: {{order.lastName}}
       Address: {{order.address}}
          City: {{order.city}}
           Zip: {{order.zip}}
         State: {{order.state}}
  </pre>
</div>

  • 1 Inputs text with v-model
  • 2 Selects Input with v-model
  • 3 <pre> tag displays data

We added our form fields for the address, city, state, and ZIP Code. The address, city, and ZIP Code are all text inputs that use the v-model directive to bind the input. Choosing a state is a little different. Instead of using a text box, we’ll use a select drop-down control. The v-model has been added to the select element.

You might wonder how we can easily add more states to our select drop-down control. For this simple example, hard-coding all four states is fine. But if we were to add all 50 states, we’d probably want to dynamically generate the select box. In the next section, we’ll look at using value bindings to help generate dynamic options.

Before we move on, let’s not forget to add our new properties to the data object in the Vue instance.

Listing 4.4. Updating the Vue instance data object with new properties: chapter-04/data-new-properties.js
data: {
  sitename: "Vue.js Pet Depot",
  showProduct: true,
  order: {
    firstName: '',
    lastName: '',
    address: '',
    city: '',
    zip: '',
    state: ''
  },

As we saw in figure 4.3, if any of these properties are changed within any of the form elements, these values are updated in the <pre> tag at the bottom. Reload the browser and your new form should look like figure 4.4.

Figure 4.4. Adding the address, city, state, and ZIP Code form fields into our checkout page.

Our form checkout page is looking good, but we need to add in a couple more things. Let’s allow our customer an option to ship items as a gift. To do this, we’ll add a simple check box. If the check box is selected, we’ll ship the items as a gift. If it isn’t, selected items won’t be shipped as a gift. To keep track of the binding we’ll use the order.gift property.

Next up, we need to allow our customer an option to ship to a home or business address. Let’s add a radio button to our code for this purpose. In Vue, we must set the v-model directive in both check boxes to the same value, otherwise the radio buttons won’t update after they’re clicked.

Finally we’ll need to update the <pre> tag with order.method and order.gift, as shown in the following listing. Add this HTML after listing 4.3 in the index.html file.

Listing 4.5. Adding check boxes and radio buttons: chapter-04/adding-buttons.html
<div class="form-group">
  <div class="col-md-6 boxes">
    <input type="checkbox"
 id="gift"
 value="true"
 v-model="order.gift">                          1
    <label for="gift">Ship As Gift?</label>
  </div>
</div>
<div class="form-group">
  <div class="col-md-6 boxes">
    <input type="radio"
      id="home"
      value="Home"
      v-model="order.method">                   2
    <label for="home">Home</label>
    <input type="radio"
      id="business"
      value="Business"
      v-model="order.method">                   2
    <label for="business">Business</label>
  </div>
</div>
<div class="col-md-12 verify">
  <pre>                                         3
    First Name: {{order.firstName}}
     Last Name: {{order.lastName}}
       Address: {{order.address}}
          City: {{order.city}}
           Zip: {{order.zip}}
         State: {{order.state}}
       Method: {{order.method}
          Gift: {{order.gift}}
  </pre>
</div>

  • 1 Adds checkbox with v-model
  • 2 Adds radio button v-model
  • 3 Updates <pre> tag with order.method and order.gift

Let’s add our properties to our data object by adding this code.

Listing 4.6. Adding more properties to our Vue data object: chapter-04/more-props.js
data: {
  sitename: "Vue.js Pet Depot",
  showProduct: true,
  order: {
    firstName: '',
    lastName: '',
    address: '',
    city: '',
    zip: '',
    state: '',
    method: 'Home',
    gift: false
  },

You may have noticed that we added default values for both method and gift. The reason behind this is simple. By default, the method radio button is selected, and the check box isn’t selected. Therefore, it would be clever of us to set a default value in this code for now.

One last thing we need to do is add a Place Order (submit) button. For now, we’ll mock out the button so we can use it the future. You have a couple of ways to create a Place Order button. You could attach an action to a form element that encompasses all our inputs. (We’ll look at this more in chapter 6 on Events.) Instead, let’s use the v-on directive that we first learned about in chapter 3. The v-on directive can bind functions to DOM elements in the application. Add it to the click event on the Place Order button. This HTML code can be added after listing 4.5.

Listing 4.7. Adding the v-on directive to the click event: chapter-04/adding-v-on.html
<div class="form-group">
  <div class="col-md-6">
    <button type="submit"
      class="btn btn-primary submit"
      v-on:click="submitForm">Place Order</button>       1
  </div>
</div>

  • 1 The Place Order button is attached to the v-on directive.

In future chapters, we’ll add functionality to our Place Order button. For our purposes now, let’s create a simple function and verify that the button works by adding an alert popup. Add the submitForm function to the method’s object that exists in the index.html file, as shown in this listing.

Listing 4.8. Creating the new submitForm method: chapter-04/submit.js
methods: {
  submitForm() {
    alert('Submitted');
...
  }
},

Inside the Vue constructor is the methods object which holds all our functions that can be triggered in the application. The submitForm function will display an alert popup when triggered. In the browser, click the Place Order button and you’ll see this popup (figure 4.5) that was triggered by the submitForm function.

Figure 4.5. This popup was triggered by the submitForm function.

Now that we have the form in place with a Place Order button, it should look like figure 4.6 when it’s all put together.

Figure 4.6. Completed checkout page with all form elements included.

Each property in the form is bound to our Vue.js model! Now let’s see if we can make our input bindings a little better.

4.2. A look at value binding

The v-model directive has been useful in binding properties for us so far. We’ve used it to bind many basic inputs. We have a problem, though. How do you bind the value for check boxes, radio buttons, and select drop-down controls? If you remember, we hard-coded the values for both check boxes and radio buttons. For our select box control, we left the values blank. All the HTML elements can, and sometimes should, have a value associated with the selected option. Instead of using hard-coded values, let’s rewrite our select box, check box, and radio buttons to use properties from our data object. Let’s begin by updating our check box with values by using the v-bind directive.

4.2.1. Binding values to our check box

In our first example, our check box was bound to the order.gift property. We could set it to be either true or false. With that said, our customers don’t want to see true or false. They’d rather see a message that lets them know if the order will be shipped as a gift. We can add that.

The v-bind directive binds values to attributes in our HTML elements. In this case, we’re binding the true-value attribute to a property. The true-value attribute is unique to the v-bind directive, and it allows us to bind properties based on the check box being checked or not, either true or false. This will change the value of the order.gift. In listing 4.9, the true-value binds to the order.sendGift property. Likewise, the false-value binds to the order.dontSendGift property. When the check box is checked, the order.sendGift message displays. If the check box isn’t checked, the order.dontSendGift property displays. Add this HTML after listing 4.8 in the index.html.

Listing 4.9. Binding true and false values to the gift check box: chapter-04/true-false.html
<div class="form-group">
  <div class="col-md-6 boxes">
    <input type="checkbox"
      id="gift" value="true"
      v-bind:true-value="order.sendGift"            1
      v-bind:false-value="order.dontSendGift"       2
      v-model="order.gift">                         3
    <label for="gift">Ship As Gift?</label>
  </div>
</div>

  • 1 Sets the order.sendGift property when the checkbox is checked
  • 2 Sets the order.dontSendGift property when the checkbox isn’t checked
  • 3 Binds order.gift to the input

To make this binding work as we expect, we’ll need to add in these new properties to our order object, as shown in the next listing. Update the order object in the index.html values with the sendGift and dontSendGift properties.

Listing 4.10. Adding the sendGift property to the order object: chapter-04/prop-gift.js
order: {
  firstName: '',
  lastName: '',
  address: '',
  city: '',
  zip: '',
  state: '',
  method: 'Business',
  gift: 'Send As A Gift',                  1
  sendGift: 'Send As A Gift',              2
  dontSendGift: 'Do Not Send As A Gift'    3
},

  • 1 The default value of checkbox defaults to the Send As A Gift check box.
  • 2 The order.sendGift property is a text message that displays when the check box is checked.
  • 3 The order.dontSendGift property is a text message that displays when the check box isn’t checked.

Our data object is getting bigger! We can now assign text values if the check box is checked or not checked. Refresh the page and uncheck the Ship As Gift check box. Look at our box at the bottom (figure 4.7); we’ll see the new values represented in the {{order.gift}} property in the UI.

Figure 4.7. The {{order.gift}} property is displayed.

Toggling the check box changes the values from the Do Not Send As A Gift to the Send As A Gift string. Note that because we set the order.gift property value to Send As A Gift, it will default the check box to checked. If needed, we could assign it to the other value. This would cause the check box to display as unchecked.

4.2.2. Working with value bindings and radio buttons

Like check boxes, we can assign values to radio buttons. We can do this by binding the value directly. This could be a useful feature for our application. Let’s display to the user the home address if the user selects the Home radio button and the business address if the user selects the Business radio button. Add this HTML to the index.html after the previous check box code.

Listing 4.11. Binding values to our radio buttons: chapter-04/radio-bind.html
<div class="form-group">
  <div class="col-md-6 boxes">
    <input type="radio"
      id="home"
      v-bind:value="order.home"              1
      v-model="order.method">
    <label for="home">Home</label>
    <input type="radio"
      id="business"
      v-bind:value="order.business"          2
      v-model="order.method">
    <label for="business">Business</label>
  </div>
</div>

  • 1 Sets the v-bind directive to the value attribute on the input element for the first radio button
  • 2 Sets the v-bind directive to the value attribute on the input element for the second radio button

The v-bind directive binds order.home to the first radio button and order.business to the second radio button. This can be powerful, because we can dynamically change these values at any time.

To finish this example, let’s add these new properties to the order object in data in the index.html, as shown in the following listing.

Listing 4.12. Updating the order object with business and home: chapter-04/update-order.html
order: {
  firstName: '',
  lastName: '',
  address: '',
  city: '',
  zip: '',
  state: '',
  method: 'Home Address',                 1
  business: 'Business Address',           2
  home: 'Home Address',                   3
  gift:'Send As A Gift',
  sendGift: 'Send As A Gift',
  dontSendGift: 'Do Not Send As A Gift'
},

  • 1 Sets the default value to the ‘Home Address’ radio button
  • 2 Displays the order.business property text message when the first radio button is selected
  • 3 Displays the order.home property text message when the second radio button is selected

This new order object now has a couple of new properties—home and business—that are bound to the radio buttons. If we select either one, the value at the bottom will toggle between Home Address and Business Address (figure 4.8).

Figure 4.8. Method is updated from the radio button.

Our customer can see that they have a package being delivered to a business address (Erik Hanchett at 123 Street Ln, Reno, NV) and it won’t be shipped as a gift! Binding properties to any attribute value in our form makes things much cleaner and easier. We now need to look at the US states select box control in the next section.

4.2.3. Learning the v-for directive

Our select box control lists US states that our customer can choose from. We need to update the select drop-down control so the state shows in our box when we refresh the page. Let’s look at how we can bind the state values. Replace the state drop-down in the index.html after the city input with the markup shown in the following listing.

Listing 4.13. Binding values to our select box: chapter-04/bind-select.html
<div class="form-group">
  <div class="col-md-2">
    <strong>State:</strong>
    <select v-model="order.state" class="form-control">
      <option disabled value="">State</option>
      <option v-bind:value="states.AL">AL</option>       1
      <option v-bind:value="states.AR">AR</option>       2
      <option v-bind:value="states.CA">CA</option>       3
      <option v-bind:value="states.NV">NV</option>       4
    </select>
  </div>
</div>

  • 1 Assigns the v-bind directive value attribute to states.AL property
  • 2 The v-bind directive value attribute is assigned to the states.AR property.
  • 3 The v-bind directive value attribute is assigned to the states.CA property.
  • 4 The v-bind directive value attribute is assigned to the states.NV property.

As we saw before, the v-bind directive is assigning our value attribute. This time we’ve created a new data property called states. Inside that states property, I’ve listed US states. The states object holds four values. We can access them inside our select box by using the v-bind directive. Update the index.html file and add the states object to the data object.

Listing 4.14. Adding the states property to the Vue instance data object: chapter-04/states.html
states: {
  AL: 'Alabama',
  AR: 'Arizona',
  CA: 'California',
  NV: 'Nevada'
},

After everything is updated, we should see these values inside our text box in our template at the bottom of the page (figure 4.9). As you can see, the state is spelled out, making it clear what’s happening.

Figure 4.9. State text property is displaying the correct state selected.

Earlier in this chapter, I mentioned a critical problem with our drop-down. In this example, only four states are listed. As we grow our list of states, we’ll need to create an option> tag for each one. This could be tedious and repetitive. Luckily, Vue has something that can help us with this. It’s called the v-for directive.

The v-for directive makes it easy to loop over values in a list or object, which is perfect for our situation. To make this work, we’ll define all our states in the state object. We’ll then iterate over every state while using the v-bind directive so everything matches. Let’s give it a shot!

Many things are happening here, so I’ll break it down. The v-for directive requires a special syntax in the form of state in states. states is the source data array, while the state is an alias for the array element that is being iterated on. In this case, state is Alabama, Arizona, California, and so on. Replace the state drop-down in the index.html after the city input with the HTML as shown here.

Listing 4.15. Updating the select drop down with v-for: chapter-04/select-drop-down.html
<div class="form-group">
  <div class="col-md-2">
    <strong>State:</strong>
    <select v-model="order.state"
      class="form-control">
      <option disabled value="">State</option>
      <option v-for="(state, key) in states"        1
           v-bind:value="state">                    2
        {{key}}                                     3
      </option>
    </select>
  </div>
</div>

  • 1 The v-for directive iterating through the state object with each key and value.
  • 2 The v-bind directive value attribute is assigned to the state property.
  • 3 The key property is displayed.

The key value is an optional argument that specifies the index of the current item. This is important in our select drop-down control because our key value can be used as the abbreviated state, while the actual value is the full state name.

The v-bind directive binds the value of state to the value on the <option> tag, as shown in listing 4.16. After replacing this code in your application, peek at the HTML that is generated by opening up your web browser and looking at the source of the index.html. The <option> tag will show every state in the states property.

Listing 4.16. HTML generated by the v-for directive: chapter-04/options.html
<option value="Alabama">
    AL
  </option>
  <option value="Alaska">
    AK
  </option>
  <option value="Arizona">
    AR
  </option>
  <option value="California">
    CA
  </option>
  <option value="Nevada">
    NV
  </option>

This is good news for our application. Because we can now bind the values and iterate over them with v-for, we no longer need to hard-code every US state. Our select box can grow dynamically based on how we create the states object.

4.2.4. The v-for directive without the optional key

I mentioned that the key value is optional, so what would a v-for directive look like without the key value? Taking a quick detour and seeing how that works, let’s start from an empty detour.html file and create a brand-new application. Create a Vue constructor and add in a data object with a states array.

Listing 4.17. Updating the states object in data: chapter 04-/detour.html
<div id="app">
  <ol>
    <li v-for="state in states">             1
      {{state}}
    </li>
  </ol>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
var webstore = new Vue({
  el: '#app',
  data: {
    states: [
      'Alabama',
      'Alaska',
      'Arizona',
      'California',
      'Nevada'
    ]
  }
})
</script>

  • 1 The v-for directive using the state in states syntax.
More

The states array has five values. Let’s create an ordered list to display each item. We don’t have any keys, so we don’t need to worry about that. To create our list, we’ll use the <ol> and <li> tags. Add these tags to the top of the new detour.html file.

The v-for directive iterates through the states array and displays each state in the list. Keep in mind that state is an alias to the array element being iterated on, whereas states is the array item. It’s easy to get this confused; remember the alias always comes first, then the optional key, then the array or object being iterated on.

When rendered, we’ll see a list of ours states in an ordered numbered list, as follows:

  1. Alabama
  2. Alaska
  3. Arizona
  4. California
  5. Nevada

We can now grow our list by adding values to our states object without having to change the template.

Note

You may run into a situation where you need to directly manipulate the DOM, and you may not want to use the v-model directive. In this instance Vue.js offers us $el. You can use $el inside your Vue instance with this.$el. This will be the root DOM element that the Vue instance is managing. From there you can run any type of Document method, like querySelector(), to retrieve any element you’d like. Remember, if you can, try to use the built-in Vue.js directives when working with the DOM. They are there to make your job easier! For more information on $el and other APIs check out the official API documentation at https://vuejs.org/v2/api/.

4.3. Learning modifiers with the application

As mentioned earlier in the chapter, the v-model directive can bind to our input values. These values update with each input event. We can use modifiers with the v-model directive to change that behavior. We can, for example, typecast values to numbers using .number and use .trim with our inputs (for more information about modifiers, go to https://vuejs.org/v2/guide/forms.html#Modifiers). We can also chain modifiers by adding one after the other (for example, v-model.trim.number). Let’s add several of these modifiers to our checkout page on the application.

4.3.1. Using the .number modifier

The .number modifier is used to automatically typecast values in the v-model directive as a number. This will be useful in our ZIP input box (we’ll assume ZIP Codes in our app don’t start with a zero, otherwise the .number modifier removes the leading zero). Let’s update the ZIP Code in the index.html file to use the .number modifier and see what effect it has in the following listing.

Listing 4.18. The .number modifier on the ZIP form element: chapter-04/number-mod.html
<div class="form-group">
  <div class="col-md-6 col-md-offset-4">
    <strong>Zip / Postal Code:</strong>
    <input v-model.number="order.zip"           1
      class="form-control"
      type="number"/>
  </div>
</div>

  • 1 Shows the v-model directive with the .number modifier

HTML inputs always return as strings, even if you add in type="number". Adding the .number modifier prevents this behavior and instead returns as a number. To verify this, let’s update the index.html with the typeof operator while displaying the order.zip property in the template.

Listing 4.19. Using the typeof operator on order.zip: chapter-04/type-of.html
<div class="col-md-12 verify">
     <pre>
       First Name: {{order.firstName}}
       Last Name: {{order.lastName}}
       Address: {{order.address}}
       City: {{order.city}}
       Zip: {{typeof(order.zip)}}        1
       State: {{order.state}}
       Method: {{order.method}}
       Gift: {{order.gift}}
     </pre>
</div>

  • 1 The JavaScript typeof operator returns the type of the unevaluated operand.

Before we added the .number modifier, it would have displayed as a string. Now it returns as a number. Type a number into the ZIP input box and re-render the page to see the new output< as seen in figure 4.10.

Figure 4.10. Type of value entered into the zip property.

You can see the ZIP column shows number in figure 4.10. Because we wrapped the ZIP Code in the typeof operand, it shows us the type of that property. We’ll be using this feature later; for now we’ll remove the typeof operand so it returns the ZIP Code. Delete the typeof operand from the order.zip property so all that remains is the property {{order.zip}}.

4.3.2. Trimming the input values

When extracting form information, we often have no use for preceding whitespace or whitespace after the text has been entered. If a user accidentally enters a few spaces before typing their name, we need to remove them. Vue.js gives us a nice modifier to trim the space automatically from our inputs.

In our application, we use input-string text boxes for the first name, last name, address, and city. In the following listing, let’s update the first name and last name in the index.html to see how the .trim modifier works.

Listing 4.20. The .trim modifier on first and last name: chapter-04/trim-mod.html
<div class="form-group">
  <div class="col-md-6">
    <strong>First Name:</strong>
    <input v-model.trim="order.firstName"       1
      class="form-control" />
  </div>
  <div class="col-md-6">
    <strong>Last Name:</strong>
    <input v-model.trim="order.lastName"        2
      class="form-control" />
  </div>
</div>

  • 1 The v-model directive uses the .trim modifier for the order.firstName property.
  • 2 The v-model directive uses the .trim modifier for the order.lastName directive.

To add the .trim modifier all we need to do is add .trim to the end of the v-model directive. This will now trim our whitespace automatically for us! Now we can add it to the address and city inputs in the index.html.

Listing 4.21. The .trim modifier on the address and city: chapter-04/trim-mod-add.html
<div class="form-group">
  <div class="col-md-12"><strong>Address:</strong></div>
  <div class="col-md-12">
    <input v-model.trim="order.address"            1
  class="form-control" />
  </div>
</div>
<div class="form-group">
  <div class="col-md-12"><strong>City:</strong></div>
  <div class="col-md-12">
    <input v-model.trim="order.city"               2
       class="form-control" />
  </div>
</div>

  • 1 The v-model directive uses the .trim modifier for the order.address property.
  • 2 The v-model directive uses the .trim modifier for the order.city directive.

If we look at the output at the bottom of the page after browser refresh, we’ll notice that the whitespace is removed (figure 4.11).

Figure 4.11. An example of using the .trim modifier on the v-model directive.

The first name input text box has the name Erik in it with many preceding whitespaces. With that said, the output at the bottom has the trimmed value on display. In fact, if we click outside the box, the value in the first name box syncs to the trimmed value. This is the power of the .trim modifier.

4.3.3. The .lazy v-model modifier

There is one last modifier that is known as the .lazy modifier. As I mentioned earlier, the v-model directive syncs after each input event. In practice, this occurs in a text box after each letter is typed. The value is synced on each keystroke. The .lazy modifier will sync on change events instead. Change events occur in a variety of situations depending on the form element used. A check box or radio button will trigger a change event when it’s clicked. An input text box will trigger a change event when it loses focus. Different browsers might not trigger change events on the same interactions, so keep that in mind.

Typically, a .lazy modifier will look like the following when added to a v-model directive:

<input v-model.lazy="order.firstName" class="form-control" />

Exercise

Use your knowledge from this chapter to answer these questions:

  • How does two-way data binding work? When should you use it in your Vue.js application?

See the solution in appendix B.

Summary

  • The v-model directive can be used to bind input, select, text areas, and components. It creates a two-way data binding on form input elements and components.
  • The v-for directive renders data multiple times based on the data that it’s given. You can use an alias in the expression on the current element being iterated on as well.
  • The v-model directive has the .trim, .lazy, and .number modifiers. The .trim modifier eliminates whitespace while the .number modifier typecasts strings as numbers. The .lazy modifier changes when data is synced.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset