Desenvolvimento Web II

Notas de aula do prof. Eduardo da disciplina de Desenvolvimento Web II (curso técnico)

View on GitHub

Tutorial para construção de um formulário

Neste tutorial, vamos construir um formulário simples para cadastro de um produto. O formulário terá os campos de nome, quantidade, preço, categorias e imagem.,

Criando o projeto

Para criar o projeto, execute o comando abaixo:

npm init vue@latest formulario

O comando anterior irá criar uma aplicação VueJS usando uma ferramenta de scaffolding chamada create-vue. Ele apresentará uma série de perguntas para você. Responda conforme a seguir (assumo que o nome da pasta e do projeto são iguais: exemplo-inicial-vue3):

✔ Project name: … formulario-vue3
✔ Add TypeScript? … No
✔ Add JSX Support? … No
✔ Add Vue Router for Single Page Application development? … No
✔ Add Pinia for state management? … No
✔ Add Vitest for Unit testing? … No
✔ Add Cypress for both Unit and End-to-End testing? … No
✔ Add ESLint for code quality? … Yes
✔ Add Prettier for code formatting? … Yes
✔ Add Vue DevTools 7 extension for debugging? … Yes

Scaffolding project in ./formulario-vue3...
Done.

Abra a pasta criada no VSCode e execute os comandos abaixo:

npm install
npm run dev

Limpando o projeto

Vamos limpar o projeto, removendo arquivos e códigos desnecessários. Edite o arquivo src/App.vue e substitua o conteúdo pelo código abaixo:

<template>
  <div>
    <h1>Formulário de Cadastro de Produtos</h1>
  </div>
</template>

Remova todos os arquivos e subpastas da pasta src/components. Edite o arquivo src/assets/main.css e substitua o conteúdo pelo código abaixo:

@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');

* {
  margin: 0;
  padding: 0;
}

body {
  font-family: 'poppins', sans-serif;
  font-size: 24px;
}

Note que o arquivo main.css importa a fonte Poppins do Google Fonts e define o estilo padrão para o corpo da página.

Criando a estrutura básica do formulário com um título editável

Vamos criar a estrutura básica do formulário. Edite o arquivo src/App.vue e substitua o conteúdo pelo código abaixo:

<script setup>
  import { ref, reactive } from 'vue';
  const titulo = ref('Formulário de Cadastro de Produtos');
</script>

<template>
  
  <h1>{{ titulo }}</h1>

  <div class="altera-titulo">
    <h2>Informe um novo título:</h2>
    <input type="text" v-model="titulo" />
  </div>
</template>

Até esse ponto, o formulário exibe um título e um campo de texto para alterar o título. O título é uma variável reativa que é vinculada ao elemento h1 e ao campo de texto. Quando o campo de texto é alterado, o título é atualizado automaticamente. Também importamos as funções ref e reactive do VueJS. A função reactive ainda não está sendo utilizada, mas será utilizada posteriormente.

Vamos fazer uma estilização básica da classe altera-titulo. Adicione o bloco style scoped neste arquivo de componente, com o seguinte conteúdo:

<style scoped>
.altera-titulo {
  background-color: #98e0aa;
  margin: 1rem 2rem;
  border-radius: 20px;
  padding: .75rem;
  display: flex;
  gap: 1rem
}
</style>

Vamos criar uma div que conterá o formulário. Adicione o código abaixo entre o h1 e a div altera-titulo:

<div class="container">
  <div class="formulario">
    <h2>Formulário para cadastro do produto</h2>
    <div class="row">
      <label for="">Nome:</label>
      <input type="text" v-model="produto.nome" />
    </div>
    <div class="row">
      <label for="">Preço (em reais):</label>
      <input type="number" step="0.01" v-model="produto.preco" />
    </div>
    <div class="row">
      <label for="">Quantidade:</label>
      <input type="number" v-model="produto.quantidade" />
    </div>

    <fieldset>
      <legend>Unidade de medida</legend>
      <div class="items-radiobox">
        <input type="radio" value="unidade" v-model="produto.medida" /> Unidades
        <input type="radio" value="peso" v-model="produto.medida" /> Peso
      </div>
    </fieldset>
    <fieldset>
      <legend>Categorias</legend>
      <div class="items-checkbox">
        <template v-for="categoria in categorias" :key="categoria.id">
          <input
            type="checkbox"
            :value="categoria.id"
            v-model="produto.categorias"
          />
           {{ categoria.nome }} 
        </template>
      </div>
    </fieldset>
    <button @click="mostrarResultado = !mostrarResultado">Mostrar</button>
  </div>
</div>

O código acima cria um formulário com os campos de nome, preço, quantidade, unidade de medida, categorias e um botão para mostrar o resultado. O formulário é estilizado com as classes container, formulario, row, items-radiobox e items-checkbox. A variável produto é um objeto reativo que armazena os dados do produto. A variável categorias é um array de objetos que armazena as categorias disponíveis para o produto. A variável mostrarResultado é uma variável reativa que controla a exibição do resultado.

Para ter um funcionamento básico, precisamos proceder com a estilização e com a criação das variáveis reativas. Adicione o código a seguir no bloco setup (pode estar logo abaixo da declaração da variável titulo):

const produto = reactive({
  nome: '',
  preco: 0,
  quantidade: 0,
  medida: '',
  categorias: [],
});

Também temos a declaração da variável categorias. Adicione o código a seguir no bloco setup (pode estar logo abaixo da declaração da variável produto):

const categorias = [
  {
    id: 1,
    nome: 'Eletrônicos',
  },
  {
    id: 2,
    nome: 'Vestuário',
  },
  {
    id: 3,
    nome: 'Brinquedos',
  },
  {
    id: 4,
    nome: 'Móveis',
  },
  {
    id: 5,
    nome: 'Alimentos',
  },
  {
    id: 6,
    nome: 'Bebidas',
  },
  {
    id: 7,
    nome: 'Informática',
  },
  {
    id: 8,
    nome: 'Papelaria',
  },
];

Por fim, o botão Mostrar será utilizado para manipular uma variável reativa booleana, que exibirá o resultado do formulário. Adicione o código a seguir no bloco setup (pode estar logo abaixo da declaração da variável categorias):

const mostrarResultado = ref(false);

Agora, vamos proceder com a estilização, adicionando o código seguinte no bloco style scoped (note que você deve manter o código atual):

.container {
  display: flex;
  justify-content: flex-start;
  gap: 2rem;
  margin-top: 1rem;
  padding: 0 2rem;
}

.formulario,
.resultado {
  width: 45vw;
  min-height: 70vh;
  border-radius: 20px;
  padding: 20px;
}

.formulario {
  background-color: #d29696;
}

.formulario .row {
  width: 80%;
  margin: 1.3rem 0;
  display: flex;
  justify-content: space-between;
}

.items-checkbox,
.items-radiobox {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
}

.resultado {
  background-color: #98e0aa;
}

button {
  padding: 0.5rem 1rem;
  border: none;
  background-color: #f1f1f1;
  border-radius: 10px;
  cursor: pointer;
}

button:hover {
  background-color: #e1e1e1;
}

Note que a estilização define a largura e a altura dos elementos formulario e resultado, além de estilizar os elementos row, items-checkbox, items-radiobox e button. Já criamos a configuração da classe resultado, mas ainda não a utilizamos. Vamos criá-la posteriormente.

Exibindo o resultado do formulário

Vamos adicionar a exibição do resultado do formulário. Vamos editar o bloco template do arquivo src/App.vue e adicionar o código abaixo, dentro da div com a classe container, logo após a div com a classe formulario:


<div v-if="mostrarResultado" class="resultado">
  <h2>Dados do produto</h2>
  <p>Nome: {{ produto.nome }}</p>
  <p>Preço: {{ formatarPreco(produto.preco) }}</p>
  <p>Em estoque: {{ produto.quantidade }}</p>
  <p>Medida: {{ produto.medida }}</p>
  <p>Categorias: {{ produto.categorias }}</p>
  <h4>Categorias selecionadas:</h4>
  <p v-for="categoria_id in produto.categorias" :key="categoria_id">
    - {{ buscarNome(categoria_id) }}
  </p>
</div>

O código acima exibe os dados do produto, incluindo o nome, o preço, a quantidade, a medida e as categorias. As categorias são exibidas como uma lista de itens. Para exibir o resultado, precisamos criar duas funções auxiliares: formatarPreco e buscarNome. Adicione o código a seguir no bloco setup (pode estar logo abaixo da declaração da variável mostrarResultado):

function formatarPreco(preco) {
  return `R$ ${preco.toFixed(2).replace('.', ',')}`;
}

function buscarNome(id) {
  return categorias.find((categoria) => categoria.id === id).nome;
}

No código acima, a função formatarPreco recebe um número e retorna uma string formatada como um valor monetário. A função buscarNome recebe um id de categoria e retorna o nome da categoria correspondente.

Alguns ajustes finais de estilização

Para finalizar, vamos editar o arquivo src/assets/main.css e adicionar o código abaixo:

input {
  width: 400px;
  padding: 10px;
  font-size: 24px;
  border-radius: 10px;
  border: 1px solid transparent;
}

input[type='checkbox'],
input[type='radio'] {
  width: 20px;
  height: 20px;
  margin: 0 10px;
}

input:hover {
  border: 1px solid black;
}

Com isso, a estilização do formulário está completa. Agora, você pode testar o formulário e ver o resultado.

O código completo do projeto está disponível no repositório do GitHub.

< Upload de imagens Exercícios ></span