Skip to content

6. progetto [vuejs-04]: direttive [v-model, v-bind], attributi calcolati, modulo di immissione

La struttura ad albero del progetto [vuejs-04] è la seguente:

Image

6.1. Lo script principale [main.js]

È lo stesso dell’esempio precedente.

6.2. Il componente principale [App]

Il codice di [App.vue] è il seguente:


<template>
  <b-container>
    <b-card>
      <!-- messaggio di presentazione -->
      <b-row>
        <b-col cols="8">
          <b-alert show variant="success" align="center">
            <h4>[vuejs-04] : directives [v-model, v-bind], attributs calculés, formulaire de saisie</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>

Il componente [App.vue] utilizza il nuovo componente [Form] (righe 12, 19, 24).

6.3. Il componente [Form]

Il codice del componente [Form] è il seguente:


<template>
  <div>
    <!-- modulo -->
    <b-form>
      <!-- elementi del modulo -->
      <b-row>
        <b-col cols="4">
          <b-card bg-variant="light">
            <b-form-group label="Nombre d'enfants à charge" label-for="enfants">
              <b-input type="text"
                       id="enfants"
                       placeholder="Indiquez votre nombre d'enfants"
                       v-model="enfants"
                       v-bind:state="enfantsValide" />
              <b-form-invalid-feedback :state="enfantsValide">Vous devez saisir un nombre positif ou nul</b-form-invalid-feedback>
            </b-form-group>
            <!-- pulsante -->
            <b-button variant="primary" :disabled="formInvalide" @click="doSomething">Valider</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>enfants= {{enfants}}</h4>
        </b-alert>
      </b-col>
    </b-row>
  </div>
</template>

<!-- script -->
<script>
  export default {
    // nome
    name: "Form",
    // attributi statici del componente
    data() {
      return {
        // numero di elementi figli
        enfants: ""
      };
    },

    // attributi calcolati
    computed: {
      // attributo [formInvalide]
      formInvalide() {
        return !this.enfantsValide;
      },
      // attributo [enfantsInvalide]
      enfantsValide() {
        return Boolean(this.enfants.match(/^\s*\d+\s*$/));
      }
    },
    // metodi
    methods: {
      doSomething() {
        // il numero di figli è noto al momento della convalida
        alert("Nombre d'enfants : " + this.enfants);
      }
    }
  };
</script>

Rendering visivo

Image

Image

Commenti

  • righe 4-32: il tag <b-form> introduce un modulo Bootstrap;
  • riga 6: il tag <b-row> introduce una riga nel modulo;
  • riga 7: il tag <b-col cols=’4’> introduce una colonna che occupa 4 colonne Bootstrap;
  • riga 8: il tag <b-card> [6] introduce una scheda Bootstrap, ovvero un'area delimitata da un bordo;
  • riga 9: il tag <b-form-group> introduce un gruppo di elementi del modulo collegati tra loro. In questo caso, un testo (attributo [label]) [1] è collegato a un campo di immissione (attributo [label-for]). Il valore di [label-for] è il valore del campo [id], riga 12, del campo di immissione;
  • righe 10-14: il tag <b-input> [2] introduce un campo di immissione:
    • riga 10: [type=’text’] indica che è possibile digitare del testo nell’area di immissione. Si sarebbe potuto scrivere [type=’number’] con i vincoli [min=’val1’ max=’val2’ step=’val3’], poiché ci si aspetta un numero di elementi figli. Abbiamo inserito [type=’text’] per mostrare come verificare la validità di un dato inserito;
    • riga 12: l’attributo [placeholder] [3] definisce il messaggio visualizzato nell’area di immissione finché l’utente non ha digitato nulla;
    • riga 13: la direttiva [v-model] associa, in modo bidirezionale, il valore inserito all’attributo [enfants], riga 42, del componente:
      • quando il valore inserito cambia, cambia anche il valore dell’attributo [enfants];
      • quando il valore dell’attributo [enfants] cambia, cambia anche il valore immesso, ovvero cambia il contenuto di [2];
      • il punto importante da comprendere è che, grazie al meccanismo descritto in precedenza, quando l’utente fa clic sul pulsante [Valider] [5], l’attributo [enfants] della riga 42 assume come valore quello inserito in [2];
    • riga 14: la direttiva [v-bind] introduce un collegamento tra, da un lato, un attributo del tag <b-input>, in questo caso l’attributo [state], e, dall’altro, un attributo del componente, in questo caso [enfantsValide], alla riga 53. L’attributo [enfantsValide] è particolare in quanto si tratta di una funzione che restituisce il valore dell’attributo. Questo tipo di attributo viene definito «attributo calcolato». Gli attributi calcolati si trovano nella proprietà [computed], riga 47, del componente. Gli attributi calcolati si utilizzano allo stesso modo degli attributi statici della funzione [data]: alla riga 14 non si scrive [v-bind:state=’enfantsValide()’], ma [v-bind:state=’enfantsValide’], senza le parentesi. Inoltre, leggendo il codice [template], non è possibile distinguere un attributo calcolato da un attributo statico. A tal fine è necessario esaminare il codice dello script del componente;
    • riga 14: l’attributo [state] determinerà lo stato valido/non valido del valore inserito: se [enfantsValide] restituisce il valore [true], il valore inserito è considerato valido, altrimenti non valido. La schermata sopra riportata mostra il componente [b-input] quando la funzione [enfantsValide] restituisce il valore [false];
    • riga 15: il tag <b-form-invalid-feedback> [4] consente di visualizzare un messaggio quando l’immissione in [2] non è valida. Il suo attributo [:state=’enfantsValide’] è identico all’attributo [v-bind:state=’enfantsValide’] della riga 14. È possibile omettere la direttiva [v-bind], ma è necessario mantenere il segno [:]. Il messaggio di errore viene quindi visualizzato quando l’attributo [enfantsValide] ha il valore [false];
    • riga 16: fine del gruppo di elementi <b-group>;
    • riga 18: il pulsante [5] che consentirà di confermare l'inserimento:
      • sarà di colore blu [variant=’primary’];
      • [:disabled="formInvalide"]: l’attributo [disabled] consente di abilitare/disabilitare il pulsante. Questo attributo è collegato (v-bind) all’attributo calcolato [formInvalide] della riga 49;
      • [@click="doSomething"]: quando l'utente cliccherà sul pulsante, verrà eseguito il metodo [doSomething], riga 59;
    • righe 19-22: chiusura dei vari tag aperti;
    • righe 23-29: una nuova riga nel [template]. [class=’mt-3’] significa [margin (m) top (t) égale à 3 spacers]. [spacer] è una misura di spaziatura di Bootstrap. Questa classe genera la spaziatura [8] nella schermata sopra riportata. Senza questa classe, l’area [7] è attaccata all’area [1-6];
    • riga 24: una colonna che occupa 4 colonne Bootstrap;
    • righe 25-27: un avviso [warning] che mostra il valore dell’attributo statico [enfants] (riga 42). Poiché questo attributo ha un collegamento bidirezionale con il campo di immissione, non appena l’utente lo modifica, cambia anche il valore visualizzato nell’avviso;
    • righe 34-65: il codice jS del componente;
    • riga 42: l’unico attributo statico del componente;
    • righe 47-56: gli attributi calcolati del componente;
    • righe 53-55: l’immissione è considerata valida se si tratta di un numero intero positivo, eventualmente preceduto o seguito da «spazi»;
    • righe 49-51: il modulo è considerato valido se l’immissione del numero di figli è valida. In generale, un modulo presenta più campi di immissione ed è considerato valido se tutti questi sono validi;
    • righe 58-63: i metodi del componente che reagiscono ai suoi eventi. In questo caso, c’è un solo evento: il [click] sul pulsante. Ci limitiamo a visualizzare il valore inserito per dimostrare che abbiamo effettivamente accesso ad esso;

6.4. Esecuzione del progetto

Modifichiamo il file [package.json] ed eseguiamo il progetto:

Image