How is the 'Two way data Binding' process with pure JS?

Asked

Viewed 1,741 times

7

Today’s Java framework is popular, such as React, Vue and Angular.

They work with Two-Way Data Binding which is a hand in the wheel for the developer.

How is this process done? Is there any simple way to accomplish this process?

I would like something educational if possible.

  • I created an example here: https://github.com/andreustimm/knockoutjs_localforage may help you understand. It uses Knockout JS and Localforage (offline)

2 answers

4


Understand, make a Two-Way Data Binding from nothing is much more complicated than it seems, after all you will have to predict all scenarios, so I strongly advise you not to try it, and use a tool like the VueJS or React.

In the example below, the Two-Way Data Binding involves only two diretivas, in the case data-html and data-value, where we are assuming that they will be one span and a input[type='text']. In a real scenario, you would have to treat the behavior of these directives in different types of Htmlelement, as a select or input[type='radio']

The second point is that we have to change the object that will serve as a model, overwriting its get and set.

Below follows a functional example, but keep in mind, the same is far from being something mature enough to be adopted as a Blibioteca.

// definindo um modelo
var model = {
  teste1: 'Hello World',
  teste2: 'Olá Mundo'
};

(function () {
  // buscando todos os HTMLElement com a diretiva data-value
  var values = document.querySelectorAll("[data-value]")
  // buscando todos os HTMLElement com a diretiva data-html
  var htmls = document.querySelectorAll("[data-html]")
  // criando um indice para os HTMLElements com a diretiva data-value
  values = [].reduce.call(values, function (values, value) {
    if (!values[value.dataset.value])
      values[value.dataset.value] = [];
    values[value.dataset.value].push(value)
    return values
  }, {})
  // criando um indice para os HTMLElements com a diretiva data-html
  htmls = [].reduce.call(htmls, function (htmls, html) {
    if (!htmls[html.dataset.html])
      htmls[html.dataset.html] = [];
    htmls[html.dataset.html].push(html)
    return htmls
  }, {})  
  
  // criando um evento para os HTMLElements com a diretiva data-value
  // quando o mesmo for atualizado pelo Usuario, deverá refletir no modelo
  // ao refletir no modelo, este deverá ser propagado para o restante da pagina.
  var onValueInput = function (evt) {
    model[this.key] = this.input.value
  }
  Object.keys(values).forEach(function (key) {
    var inputs = values[key]
    inputs.forEach(function (input) {
      input.addEventListener("input", onValueInput.bind({ key, input }))
    })
  })
  // modificando as propriedades de acesso do modelo
  Object.keys(model).forEach(function (key) {
    var _value = model[key]
    Object.defineProperty(model, key, {
      // get: retorna o valor para de uma determinada propriedade do modelo
      get: function () {
        return _value;
      },
      // set: ao setar algum valor no modelo, deve se propagar o mesmo para os HTMLElements
      // com diretivas associadas a esta propriedade
      set: function (value) {
        _value = value
        if (values[key]) {
          var inputs = values[key]
          inputs.forEach(function (input) {
            input.value = _value
          })
        }
        if (htmls[key]) {
          var spans = htmls[key]
          spans.forEach(function (span) {
            span.textContent = _value
          })
        }
      }
    })
    // atualizando a pagina com os valores iniciais
    model[key] = _value
  })
})();

// atualizando os valores do modelo após 5 segundos (apenas para demonstrar o 2-way data binding)
window.setTimeout(function () {
  model.teste1 += " - deprecated"
  model.teste2 += " - descontinuado"
}, 5000)
<input type="text" data-value="teste1" />
<br />
<span data-html="teste1"></span>
<br />
<input type="text" data-value="teste2" />
<br />
<span data-html="teste2"></span>
<br />
<br />
Recaptulando, Os textos são <span data-html="teste1"></span> e <span data-html="teste2"></span>

3

Two-way data Binding or two-way connection means basically the following:

  • When the data/elements of the interface (frontend) user are updated/included
    • Changes are propagated to the model (backend/controller/javascript)
    • To pass through the business irrigation and if necessary record in the database
  • When the properties in the model (backend) are included/updated
    • The same goes for interface (frontend/layout/html) user’s
    • For the user to view the data changed/recorded by the system

Example simple using only a few-line function with JavaScript pure:

twoWay = function(event) {
  var elem = document.getElementsByClassName(event.currentTarget.className);
  for(var key in elem){
    elem[key].value = event.currentTarget.value;
  }
}
<title>Exemplo Two Way data binding</title>
<body style="background: whitesmoke;">

  Nome : <input type="text" class="username" onkeyup="twoWay(event);" >
  <input type="text" class="username" onkeyup="twoWay(event);"> <br>
  
  Idade : <input type="text" class="idade" onkeyup="twoWay(event);" >
  <input type="text" class="idade" onkeyup="twoWay(event);">
  <input type="text" class="idade" onkeyup="twoWay(event);">
</body>


Other example (code only):


References:

Browser other questions tagged

You are not signed in. Login or sign up in order to post.