6. project [vuejs-04]: directives [v-model, v-bind], computed properties, input form
The directory structure of the [vuejs-04] project is as follows:

6.1. The main script [main.js]
It is the same as in the previous example.
6.2. The main component [App]
The code for [App.vue] is as follows:
<template>
<b-container>
<b-card>
<!-- introductory message -->
<b-row>
<b-col cols="8">
<b-alert show variant="success" align="center">
<h4>[vuejs-04]: [v-model, v-bind] directives, computed properties, input form</h4>
</b-alert>
</b-col>
</b-row>
<Form />
</b-card>
</b-container>
</template>
<script>
import Form from "./components/Form.vue";
export default {
name: "app",
components: {
Form
}
};
</script>
The [App.vue] component uses the new [Form] component (lines 12, 19, 24).
6.3. The [Form] component
The code for the [Form] component is as follows:
<template>
<div>
<!-- form -->
<b-form>
<!-- form elements -->
<b-row>
<b-col cols="4">
<b-card bg-variant="light">
<b-form-group label="Number of dependent children" label-for="children">
<b-input type="text"
id="children"
placeholder="Enter the number of children"
v-model="children"
v-bind:state="validChildren" />
<b-form-invalid-feedback :state="childrenValid">You must enter a positive number or zero</b-form-invalid-feedback>
</b-form-group>
<!-- button -->
<b-button variant="primary" :disabled="formInvalid" @click="doSomething">Submit</b-button>
</b-card>
</b-col>
</b-row>
</b-form>
<b-row class="mt-3">
<b-col cols="4">
<b-alert show variant="warning" align="center">
<h4>children= {{children}}</h4>
</b-alert>
</b-col>
</b-row>
</div>
</template>
<!-- script -->
<script>
export default {
// name
name: "Form",
// static component attributes
data() {
return {
// number of children
children: ""
};
},
// computed properties
computed: {
// [formInvalid] property
formInvalid() {
return !this.validChildren;
},
// attribute [childrenInvalid]
childrenValid() {
return Boolean(this.children.match(/^\s*\d+\s*$/));
}
},
// methods
methods: {
doSomething() {
// the number of children is known when validation occurs
alert("Number of children: " + this.children);
}
}
};
</script>
Visual output


Comments
- lines 4–32: the <b-form> tag introduces a Bootstrap form;
- line 6: the <b-row> tag introduces a row in the form;
- line 7: the <b-col cols=’4’> tag introduces a column spanning 4 Bootstrap columns;
- line 8: the <b-card> tag [6] introduces a Bootstrap card, an area framed by a border;
- line 9: the <b-form-group> tag adds a group of form elements linked to each other. Here, a label (the [label] attribute) [1] is linked to an input field (the [label-for] attribute). The value of [label-for] is the value of the [id] field (line 12) of the input field;
- lines 10–14: the <b-input> tag [2] introduces an input field:
- line 10: [type='text'] indicates that text can be typed into the input field. We could have written [type='number'] with constraints [min='val1' max='val2' step='val3'] since we expect a number of children. We used [type='text'] to demonstrate how to validate an input;
- line 12: the [placeholder] attribute [3] sets the message displayed in the input field until the user enters something;
- line 13: the [v-model] directive bidirectionally binds the entered value to the [children] attribute, line 42, of the component:
- when the entered value changes, the value of the [children] attribute also changes;
- when the value of the [children] attribute changes, the entered value also changes, i.e., the content of [2] changes;
- the important point to understand is that, thanks to the mechanism described above, when the user clicks the [Validate] button [5], the [children] attribute on line 42 takes on the value entered in [2];
- Line 14: The [v-bind] directive establishes a binding between an attribute of the <b-input> tag—in this case, the [state] attribute—and a component attribute—in this case, [enfantsValide] on line 53. The [enfantsValide] attribute is unique in that it is a function that returns the attribute’s value. This type of attribute is called a computed attribute. Computed attributes are found in the [computed] property, line 47, of the component. Computed attributes are used in the same way as static attributes of the [data] property: On line 14, we do not write [v-bind:state=’enfantsValide()’] but [v-bind:state=’enfantsValide’], without the parentheses. Therefore, when reading the [template], it is impossible to distinguish a computed attribute from a static attribute. To do so, one must examine the component’s script code;
- Line 14: The [state] attribute sets the valid/invalid status of the entered value: if [enfantsValide] returns [true], the entered value is considered valid; otherwise, it is considered invalid. The screenshot above shows the [b-input] component when the [enfantsValide] function returns [false];
- Line 15: The <b-form-invalid-feedback> tag [4] displays a message when the input in [2] is invalid. Its attribute [:state='childrenValid'] is identical to the attribute [v-bind:state='childrenValid'] in line 14. The [v-bind] directive can be omitted, but the [:] symbol must be retained. The error message is therefore displayed when the [childrenValid] attribute is [false];
- line 16: end of the <b-group> element group;
- line 18: the [5] button that will validate the input:
- it will be blue [variant='primary'];
- [:disabled="formInvalide"]: the [disabled] attribute enables or disables the button. This attribute is bound (v-bind) to the computed attribute [formInvalide] on line 49;
- [@click="doSomething"]: when the user clicks the button, the [doSomething] method on line 59 will be executed;
- lines 19–22: closing the various open tags;
- lines 23–29: a new line in the [template]. [class=’mt-3’] means [margin (m) top (t) equal to 3 spacers]. [spacer] is a Bootstrap spacing unit. This class creates the spacing [8] in the screenshot above. Without this class, area [7] is flush with areas [1-6];
- line 24: a column spanning 4 Bootstrap columns;
- lines 25–27: a [warning] alert displaying the value of the static [children] attribute (line 42). Since this attribute has a two-way binding with the input field, as soon as the user modifies it, the value displayed in the alert also changes;
- lines 34–65: the component’s JavaScript code;
- line 42: the component’s single static attribute;
- lines 47–56: the component’s calculated attributes;
- lines 53–55: the input is considered valid if it is a positive integer, optionally preceded or followed by spaces;
- lines 49–51: the form is considered valid if the number of children entered is valid. Generally, a form has multiple fields and is considered valid if all of them are valid;
- lines 58–63: the component’s methods that respond to its events. Here, there is only one event: the [click] on the button. We simply display the entered value to show that we have access to it;
6.4. Running the project
We modify the [package.json] file and run the project:
