Skip to content

6. projeto [vuejs-04]: diretrizes [v-model, v-bind], atributos calculados, formulário de introdução de dados

A estrutura do projeto [vuejs-04] é a seguinte:

Image

6.1. O script principal [main.js]

É o mesmo que no exemplo anterior.

6.2. O componente principal [App]

O código de [App.vue] é o seguinte:


<template>
  <b-container>
    <b-card>
      <!-- mensagem de apresentação -->
      <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>

O componente [App.vue] utiliza o novo componente [Form] (linhas 12, 19, 24).

6.3. O componente [Form]

O código do componente [Form] é o seguinte:


<template>
  <div>
    <!-- formulário -->
    <b-form>
      <!-- elementos do formulário -->
      <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>
            <!-- botão -->
            <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",
    // atributos estáticos do componente
    data() {
      return {
        // número de filhos
        enfants: ""
      };
    },

    // atributos calculados
    computed: {
      // atributo [formInvalide]
      formInvalide() {
        return !this.enfantsValide;
      },
      // atributo [enfantsInvalide]
      enfantsValide() {
        return Boolean(this.enfants.match(/^\s*\d+\s*$/));
      }
    },
    // métodos
    methods: {
      doSomething() {
        // o número de filhos é conhecido no momento da validação
        alert("Nombre d'enfants : " + this.enfants);
      }
    }
  };
</script>

Apresentação visual

Image

Image

Comentários

  • linhas 4-32: a baliza <b-form> insere um formulário Bootstrap;
  • linha 6: a baliza <b-row> introduz uma linha no formulário;
  • linha 7: a baliza <b-col cols=’4’> insere uma coluna que ocupa 4 colunas do Bootstrap;
  • linha 8: a baliza <b-card> [6] introduz um cartão Bootstrap, uma área delimitada por uma moldura;
  • linha 9: a baliza <b-form-group> introduz um grupo de elementos do formulário interligados entre si. Aqui, um texto (atributo [label]) [1] está ligado a um campo de introdução de dados (atributo [label-for]). O valor de [label-for] é o valor do campo [id], linha 12, do campo de introdução de dados;
  • linhas 10-14: a baliza <b-input> [2] introduz um campo de entrada:
    • linha 10: [type=’text’] indica que é possível digitar texto na área de entrada. Poderíamos ter escrito [type=’number’] com restrições [min=’val1’ max=’val2’ step=’val3’], uma vez que se espera um número de elementos filhos. Utilizámos [type=’text’] para mostrar como verificar a validade de uma entrada;
    • linha 12: o atributo [placeholder] [3] define a mensagem exibida na área de introdução de dados enquanto o utilizador não tiver introduzido nada;
    • linha 13: a diretiva [v-model] associa, de forma bidirecional, o valor introduzido ao atributo [enfants], linha 42, do componente:
      • quando o valor introduzido muda, o valor do atributo [enfants] também muda;
      • quando o valor do atributo [enfants] muda, o valor introduzido também muda, ou seja, o conteúdo de [2] muda;
      • o ponto importante a compreender é que, graças ao mecanismo anterior, quando o utilizador clica no botão [Valider] [5], o atributo [enfants] da linha 42 assume como valor o valor introduzido em [2];
    • linha 14: a diretiva [v-bind] estabelece uma ligação entre, por um lado, um atributo da baliza <b-input>, neste caso o atributo [state], e, por outro, um atributo do componente, neste caso [enfantsValide], na linha 53. O atributo [enfantsValide] é particular, na medida em que se trata de uma função que devolve o valor do atributo. A este tipo de atributo chama-se «atributo calculado». Os atributos calculados encontram-se na propriedade [computed], linha 47, do componente. Os atributos calculados utilizam-se da mesma forma que os atributos estáticos da função [data]: na linha 14, não se escreve [v-bind:state=’enfantsValide()’], mas sim [v-bind:state=’enfantsValide’], sem os parênteses. Além disso, ao ler o [template], não é possível distinguir um atributo calculado de um atributo estático. Para tal, é necessário consultar o código do script do componente;
    • linha 14: o atributo [state] irá definir o estado válido/inválido do valor introduzido: se [enfantsValide] devolver o valor [true], o valor introduzido é considerado válido; caso contrário, é considerado inválido. A captura de ecrã acima mostra o componente [b-input] quando a função [enfantsValide] devolve o valor [false];
    • linha 15: a baliza <b-form-invalid-feedback> [4] permite apresentar uma mensagem quando a entrada em [2] é inválida. O seu atributo [:state=’enfantsValide’] é idêntico ao atributo [v-bind:state=’enfantsValide’] da linha 14. É possível omitir a diretiva [v-bind], mas é necessário manter o sinal [:]. A mensagem de erro é, portanto, apresentada quando o atributo [enfantsValide] tem o valor [false];
    • linha 16: fim do grupo de elementos <b-group>;
    • linha 18: o botão [5] que permitirá validar a entrada:
      • ficará azul [variant=’primary’];
      • [:disabled="formInvalide"]: o atributo [disabled] permite ativar/desativar o botão. Este atributo está ligado (v-bind) ao atributo calculado [formInvalide] da linha 49;
      • [@click="doSomething"]: quando o utilizador clicar no botão, o método [doSomething], linha 59, será executado;
    • linhas 19-22: fecho das várias balizas abertas;
    • linhas 23-29: uma nova linha no [template]. [class=’mt-3’] significa [margin (m) top (t) égale à 3 spacers]. [spacer] é uma medida de espaçamento do Bootstrap. Esta classe gera o espaçamento [8] na captura de ecrã acima. Sem esta classe, a área [7] fica colada à área [1-6];
    • linha 24: uma coluna que ocupa 4 colunas do Bootstrap;
    • linhas 25-27: um alerta [warning] que exibe o valor do atributo estático [enfants] (linha 42). Como este atributo tem uma ligação bidirecional com o campo de introdução de dados, assim que o utilizador o altera, o valor apresentado no alerta também muda;
    • linhas 34-65: o código jS do componente;
    • linha 42: o único atributo estático do componente;
    • linhas 47-56: os atributos calculados do componente;
    • linhas 53-55: a entrada é considerada válida se for um número inteiro positivo, eventualmente precedido ou seguido por «espaços»;
    • linhas 49-51: o formulário é considerado válido se a entrada do número de filhos for válida. Em geral, um formulário tem várias entradas e é considerado válido se todas elas forem válidas;
    • linhas 58-63: os métodos do componente que reagem aos seus eventos. Aqui, existe apenas um evento: o [click] no botão. Limitamo-nos a apresentar o valor introduzido para demonstrar que temos efetivamente acesso ao mesmo;

6.4. Execução do projeto

Alteramos o ficheiro [package.json] e executamos o projeto:

Image