Skip to content

Latest commit

 

History

History
369 lines (256 loc) · 13.3 KB

README.md

File metadata and controls

369 lines (256 loc) · 13.3 KB

PROJETO DE SITE FULLSTACK DE PERGUNTAS E RESPOSTAS UTILIZANDO HTML5, CSS3, EMBEDDED JAVASCRIPT, NODE.JS, MYSQL E BOOTSTRAP

Iniciando o projeto

  • Iniciar o projeto

      npm init -y
    
  • Instalar o express

      npm i express --save
    
  • Instalar o EJS

      npm i ejs --save
    

EMBEDDED JAVASCRIPT (EJS)

  • Template Engine
  • Desenha (renderiza) o HTML na tela
  • Permite inserção de código JS no HTML

Necessário configurar ejs para exibir o html

  • Para configurar o ejs como template engine, basta inserir uma linha de código antes as rotas. Nesta linha, a variável app utiliza a função set, passando passando dois parâmetros, um é a declaração de definição da view engine e o segundo é qual será a biblioteca utilizada (nesse caso, ejs)

  • Usa-se res.render para renderizar a página criada desejada que esteja em views. A função render() terá como valor o nome do arquivo desejado

      app.set('view engine', 'ejs');
    
      app.get('/', (req, res) => {
          res.render('index');
      });
    
  • Os htmls utilizados no projeto devem ser armazenados em uma pasta views, pois, por padrão o express busca dentro desta pasta os arquivos

  • Por estar sendo usado o EJS, os arquivos terão ejs como extensão, ao invés de html

    • Apenas a extensão muda, mas a sintaxe do html permanece
  • Para renderizar arquivos dentro de pastas basta inserir o nome da pasta / o nome o arquivo, desde que a pasta esteja dentro da pasta views

      app.get('/perfil', (req, res) => {
          res.render('main/Perfil');
      });
    

Exibir variáveis no HTML

  • Para exportar as variáveis do backend, passa-se na função render() um segundo parâmetro, que é um objeto, onde os valores das chaves serão as vaiáveis que serão utilizadas. Dessa forma, render() passa a ter dois parâmetros: o primeiro é o arquivo que será renderizado e o segundo são as variáveis que serão exportadas para o arquivo ter acesso

  • O objeto também pode ter dados definidos fora de variáveis

  • A variável será acessada utilizando a propriedade definida no objeto

      app.get('/', (req, res) => {
          let nome = 'Mauricio';
          let lang = 'JavaScript';
          res.render('index', {
              nome: nome,
              lang: lang,
              empresa: 'TicBox Sistemas',
              colaboradores: 12
          });
      });
    
  • Para exibir no html variáveis vindas do backend, usa-se no html uma tag especial, que contem a variável desejada

      <p><b>Nome:</b> <%= nome %></p>
    
      <p><b>Linguagem preferida:</b> <%= lang %></p>
    
      <p><b>Empresa:</b> <%= empresa %></p>
    
      <p><b>Total de colaboradores:</b> <%= colaboradores %></p>
    

Expressões no HTML

  • Usa-se uma tag especial, que contém a estrutura

      - Estruturas condicionais
              
              <% if(msg){ %>
              
              <% } %>
              
              <% if(msg){ %>
              <h3>Mensagem de erro</h3>
              <% } %>
    
              <% if(msg){ %>
    
              <% } else { %>
    
              <% } %>
    
              <% if(msg){ %>
              <h3>Mensagem de erro</h3>
              <% } else { %>
              <h3>Mensagem de aprovação</h3>
              <% } %>
      
      - Estruturas de repetição
    
              <% produtos.forEach((produto) => { %>
    
              <% }) %>
              
              <% produtos.forEach((produto) => { %>
                      <ul><li>
                      <b>Produto:</b> <%=produto.nome%>
                      <b>Preço:</b> <%=produto.valor%>
                      </li></ul>
              <% }) %>
    
    
              <% for (let produto of produtos) { %>
                      <ul><li>
                      <b>Produto:</b> <%=produto.nome%>
                      <b>Preço:</b> <%=produto.valor%>
                      </li></ul>
              <% } %>
    
              <% for (produto of produtos) { %>
                      <% if (produto.ativo == true) { %>
                      <ul><li>
                              <b>Produto:</b> <%=produto.nome%>
                              <b>Preço:</b> <%=produto.valor%>
                      </li></ul>
                      <% } %>
              <% } %>
    

Arquivos Estáticos no Express (CSS, IMG, JS, etc.)

  • Necessário apenas realziar a configuração, executando a função use, que tem como parâmetro express.static()

  • A função static tem como parâmetro o nome da pasta que irá conter os arquivos. Por padrão de projeto, normalmente colocamos o nome desta pasta como public

              app.set('view engine', 'ejs');
              app.use(express.static('./public'));
    
  • O link com css fica da seguinte forma:

              <link rel="stylesheet" href="/css/style.css">
    
  • O link de imagens e demais arquivos seguem a mesma lógica do link de css

              <img src="/img/back.jpg" alt="fundo" class="image">
    

BOOTSTRAP

  • Baixar no site e jogar os arquivos dentro do projeto (versão 4.5 é usada neste projeto)

  • Importar o CSS e JS do bootstrap no html

              <link rel="stylesheet" href="/css/bootstrap.min.css">
    
  • Para a importação do JS são necessárias duas dependências

  • Os demais CSS, que não forem do bootstrap, devem ser colocados depois do CSS do bootstrap

  • Faz-se a importação das dependências e do arquivo JS do bootstrap

  • A ordem deve ser a exata a seguir

              <script
              src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
              integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
              crossorigin="anonymous"
              ></script>
              <script
              src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
              integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
              crossorigin="anonymous"
              ></script>
              <script src="/js/bootstrap.min.js"></script>
    

REUTILIZANDO HTML COM PARTIALS

  • Partes de layouts que podem ser reutilizadas em outras páginas (componentes)

  • Usa-se a função include para chamar o arquivo do componente desejado, apontando a propriedade partials seguido do caminho e nome do arquivo

              <%- include('partials/header.ejs') %>
    

ENVIO DE DADOS PARA O BACKEND

  • Usando GET, os dados são enviados utilizando os query params (aparecem na url)

  • Usando POST, os dados são enviados utilizando os body params (não aparecem na url)

  • É necesspario configurar o express para receber os dados do front

              // Configura o Express para receber os dados do front
              app.use(express.urlencoded({ extended: false }));
              // Permite a leitura de dados via JSON
              app.use(express.json());
    

SEQUELIZE

  • ORM (Object Relational Mapper - Mapeamento objeto-relacional)

    • Sistema para abstração da camada de Banco de Dados. Remove a necessidade de digitação das queries
  • Framework que auxilia a trabalhar com banco de Dados a partir do node

  • Seguir a documentação em https://www.npmjs.com/package/sequelize

    npm i --save sequelize

  • Necessária a instalação do módulo relativo ao Banco de Dados que será utilizado. Ver na documentação

    npm install --save mysql2

Conectando com o banco de dados

    const Sequelize = require('sequelize')
    const sequelize = new Sequelize('nome_banco', 'usuario', 'senha', {
        host: 'nome_host',
        dialect: 'banco_de_dados'
    })
    *EX*
        const Sequelize = require('sequelize')
        const sequelize = new Sequelize('test', 'root', 'root', {
        host: 'localhost',
        dialect: 'mysql'
        })

Verificando se a conexão foi bem sucedida

  • Basta adicionar ao fim do código:

      sequelize.authenticate().then(function(){
          console.log('Conectado')
      }).catch(function(erro) {
          console.log('Falha na conexão' + erro)
      })
    

then

  • Funciona como uma funcção de callback. Neste caso para sequelize.authenticate(), de forma que caso a conexão seja estabelecida, será chamada.

catch

  • Funciona como uma funcção de callback. Neste caso para sequelize.authenticate(), de forma que caso a conexão seja estabelecida, será chamada.

  • As funções funcionam como if/else que testa se a conexão foi estabelecida, onde then é if e catch é else

    • As funções then e catch fazem parte do paradgma Programação Assincrona

Criando model

  • Model é uma referência de uma tabela no Sequelize, podendo ser usado para manipular o Banco de Dados

Criar tabelas

  • Cria-se uma variável, atribuindo a ela a variável sequelize, utilizando a função define(), passando como parâmetro o nome da tabela e seus campos com seus tipos, de acordo com o Sequelize

      const Postagem = sequelize.define('postagens', {
          titulo: {
              type: Sequelize.STRING
          },
          conteudo: {
              type: Sequelize.TEXT
          }
      })
    

STRING

- Possui limite de caracteres
- Varchar (255)

TEXT

- Não possui limite de caracteres
- Text

INTERGER

- Int

allowNull

    - Define se o campo será not null
  • Para que o comando seja executado, usa-se a função sync ao chamar a variável criada, passando como parãmetro o objeto force, que determinará se o Sequelize irá forçar a criação da tabela mesmo que ela exista. Force recebe um valor booleano

      const Postagem = sequelize.define('postagens', {
      titulo: {
          type: Sequelize.STRING
      },
      conteudo: {
          type: Sequelize.TEXT
      }
      })
    
      Postagem.sync({force: true})
    

Inserir dados nas tabelas

  • Chama-se o model e usa-se a função create, passando como parâmetro, os campos com seus valores

      Postagem.create({
      titulo: 'Teste de Titulo',
      conteudo: 'Teste de conteudo'
      })
    

Exibindo na tela dados do Banco de Dados

  • Usa-se a função findAll atribuida à variável referente ao model da tabela que deseja exibir os dados

              app.get('/', function(req, res) {
              Post.findAll()
              res.render('Home')
              })
    
  • Após isso, usa-se a função then atribuida a Post.findAll(), passando uma função que tem um parâmetro, e como valor, passa-se a função render atrubuida a res

  • Render recebe como valor o nome da página que será renderizada e um objeto que possui como propriedade e valor da propriedade o parâmetro passado na função em .then

  • Isto fornece para apágina indicada o acesso aos dados da tabela no banco de dados

              app.get('/', function(req, res) {
              Post.findAll().then(function(posts) {
              res.render('Home', {posts: posts})
              })
              })
    
  • O conteúdo pode ser ordenado passando para a função findAll um objeto com o atributo order e que tem como valor um array englobado por colchetes, onde o primeiro valor será a coluna que será referenciada para ordenamento e o segundo valor será o tipo de oredem: ascendente ou descentente

              app.get('/', function(req, res) {
              Post.findAll({order: [['id', 'desc']]}).then(function(posts) {
              res.render('Home', {posts: posts})
              })
              })
    
  • Podemos obrigar o sequelize a mostrar no console apenas os registros do banco, sem informações adicionais, utilizando a propriedade raw

              app.get('/', function(req, res) {
              Post.findAll({order: [['id', 'desc']], raw: true}).then(function(posts) {
              res.render('Home', {posts: posts})
              })
              })
    

Exibindo as perguntas no EJS

  • Percorre-se o array de dados do banco para que sejam exibidos

              <%perguntas.forEach((pergunta) => {%>
                  <h2 class="titulo-lista"><%= pergunta.titulo %></h2>
                  <ul type="none">
                  <li class="item-lista"><%= pergunta.descricao %></li>
                  </ul>
              <%})%>
    

Exibindo as respostas

  • Necessário realizar a busca pelas respostas dentro da rota da pergunta, para que seja diponiblizada para o front

              app.get('/pergunta/:id', (req, res) => {
                  let idFront = req.params.id;
                  Pergunta.findOne({
                      where: { id: idFront }
                  }).then((result) => {
                      if (result != undefined) {
    
                          Resposta.findAll({
                              raw: true,
                              where: { idPergunta: result.id }
                          }).then((respostas) => {
    
                              res.render(
                                  'pergunta', {
                                      perguntas: result,
                                      respostas: respostas
                                  }
                              );
                              console.log(respostas);
                          });
                      } else {
                          res.redirect('/');
                      }
                  }).catch((err) => {
                      console.log(err);
                  });
              });