DEV Community

Wanderson Alves Rodrigues
Wanderson Alves Rodrigues

Posted on

Two-way data binding com JavaScript

Vou mostrar como fazer um two-way data binding sem usar nenhum framework só com Javascript puro.

Two-way data binding, é o termo dado a reatividade dos elementos na sua interface. Ou seja, o que acontece no DOM (View), reflete no JavaScript(Model), e o que acontece no JavaScript(Model), reflete no DOM(View).

Alt Text

No exemplo que vou disponibilizar dois botões um para incrementar o valor e outra para decrementar, qualquer interação com os botões temos a atualização do DOM que é exibida no input e também atualiza o Model no Javascript.

Alt Text

Alt Text

1 - Criar o projeto

Crie uma pasta e nela adicione os arquivos index.js e index.html.

2 - HTML

No HTML temos o seguinte código abaixo:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- CSS only -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
  <title>Two way data binding</title>
</head>

<body>

  <div class="container py-5">
    <form class="row g-3">
      <div class="col-auto">
        <input min="0" type="number" class="form-control" id="ipt-number" placeholder="Número" disabled>
      </div>
      <div class="col-auto">
        <button type="button" class="btn btn-success mb-3" onclick="increment()">(+)</button>
        <button type="button" class="btn btn-danger mb-3" onclick="decrement()">(-)</button>
      </div>
    </form>
  </div>

  <script src="index.js"></script>
  <!-- JavaScript Bundle with Popper -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj" crossorigin="anonymous">
  </script>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode
  • Para a estilização optei por usar o Bootstrap, por isso foi adicionado o CSS e Javascript.

CSS:

  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
Enter fullscreen mode Exit fullscreen mode

Javascript:

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj" crossorigin="anonymous">
Enter fullscreen mode Exit fullscreen mode
  • O código é bem simples pois temos um input disabled que será o alvo das alterações do valor no DOM e dois botões (+) que lança a ação de incrementar e o (-) que lança a ação de decrementar.

  • As ações são disparadas pelo evento onclick de clique em qualquer botão que chama as funções correspondentes;

3 - Javascript

A interação com o DOM encontra-se no Javascript, e nela que vamos usar a propriedade Object.defineProperty para manipular nosso objeto que será atualizado de acordo com o valor do input e por ações podemos atualizar o DOM.

O código pode ser visto abaixo:

const model = {
  value: ""
};

load = () => {
  const number = document.getElementById("ipt-number");
  number.value = "0";

  Object.defineProperty(model, "prop", {
    get: function () {
      console.log("Getter called");
      return this.value;
    },
    set: function (value) {
      console.log("Setter called", value);
      this.value = value;
      printVal();
    }
  });
};

increment = () => {
  let val = parseInt(model.prop || 0) + 1;
  model.prop = val;
};

decrement = () => {
  let val = parseInt(model.prop || 0) - 1;
  if (val < 0) val = 0;
  model.prop = val;
};

printVal = () => {
  const el = document.getElementById("ipt-number");
  el.value = model.prop;
};

load();
Enter fullscreen mode Exit fullscreen mode
  • load: Nessa função temos a inicialização do input com o valor zero e a criação do manipulador do nosso objeto através da propriedade Object.defineProperty;

  • Object.defineProperty: Como primeiro parâmetro definimos o objeto que será definida as propriedades, depois a propriedade que será definida ou alterada e por ultimo uma função com os métodos get e set. Quando queremos atualizar o objeto model usamos o set e para obter o valor atual usamos o get;

  • increment: Nessa função é a ação de incrementa o valor do objeto model, pegamos o valor atual model.prop e depois de executar alguma regra no caso uma soma com 1 atualizamos o nosso objeto model model.prop = val com o novo valor;

  • decrement: Nessa função é a ação que decrementa o valor do objeto model, então pegamos o valor atual do model, pegamos o valor atual model.prop e depois de executar alguma regra no caso o valor atual menos 1 atualizamos o nosso objeto model model.prop = val com o novo valor;

  • printVal: Nessa função para cada ação de incrementar ou decrementar o método set é disparado para atualizar o DOM;

O código pode ser obtido no Github.

Discussion (0)