Two way data binding

Como implementar?

Minha caminhada com Javascript é bem breve. Assim como a maioria das pessoas, após aprender o bom e velho Vanilla, procurei um framework que pudesse me ajudar a desenvolver aplicações mais complexas de forma mais ágil.

Após pesquisar um pouco, encontrei o famoso Angular da Google que tinha uma proposta um tanto nova…o conhecido hoje, Two Way Data Binding!

Hmm, mas o que é Two Way Data Binding?

Two Way Data Binding pode parecer um pouco confuso no início, para aqueles que estão acostumados com a forma que Vanilla ou JQuery leva os dados do Javascript para o DOM e do DOM para o Javascript.

Pois bem, a proposta principal do Two Way Data Binding é automatizar esse trafego de dados, de tal forma que o desenvolvedor não precise mais criar handlers no DOM para atualizar o Javascript e vice versa. Assim, quando um valor no DOM mudar, o Javascript responsável por aquele DOM também vai será atualizado com o respectivo valor automaticamente sem precisar adicionar qualquer handler, como por exemplo:

// HTML
<input onkeyup=”onChange”>
//Javascript
window.onChange = function (event){  }

Parece algo complicado, né? Mas na verdade é bem simples de ser implementado. :)

A imagem a baixo é um fluxograma de como funciona a lógica de atualização dos dados com Two Way Data Binding:

A imagem a cima cita duas palavras chaves: View e Model.

Nesse escopo, View seria o DOM e Model seria o Javascript responsável por controlar o fluxo de dados para o DOM.

Maneiro, mas e o código? Cadê?

Depois dessa breve introdução ao conceito dessa tecnologia, chegou a hora implementar nosso próprio Two Way Data Binding! Bora codificar!

Crie um arquivo html com o seguinte conteúdo:

<input my-input=”name”>

Como você pode ver o atributo my-input é um atributo customizado e será usado para manipular os valores de entrada quando digitamos algo no campo input.

Adicione a tag script abaixo do campo input, pois vamos adicionar nosso código js dentro delas (isso é uma má prática, então não faça isso no mundo real).

Dentro da tag script, será preciso buscar o elemento que contém o atributo my-input para que possamos “escutar” os valores que são passados para esse elemento. Adicione o seguinte Javascript:

var model = {};
var input = document.querySelector('[my-input]');
var modelProperty = input.getAttribute('my-input');
input.addEventListener('keyup', function (e) {
model[modelProperty] = e.target.value;
});

O código a cima apenas busca o elemento que contém o atributo my-input e após recuperar sua referência, pega o valor que o atributo contém, que nesse caso é o valor “name” (conforme colocamos no html). Esse valor “name” será a propriedade que será modificada no model, que como podemos ver no Javascript a cima…é apenas um Objeto.

Usaremos o evento keyup para atualizarmos em tempo real o model.

Legal, mas como refletir as alterações do Model no DOM?

Quando estava desenvolvendo o meu próprio Two Way Data Binding, fiquei algum tempo refletindo sobre essa parte.

Afinal, como fazer com que o model saiba quando deve atualizar o DOM?

Depois de um tempo pesquisando, resolvi usar o watch do Javascript que funcionou muito bem para essa necessidade!

Agora que sabemos o que usar para implementar essa necessidade, vamos botar a mão na massa!

Adicione logo abaixo do elemento que contém o my-input, um novo elemento contendo o atributo my-output.

<span my-output="name"></span>

O atributo my-output será o responsável por refletir no DOM as alterações feitas na propriedade “name” do Model.

Agora precisamos adicionar o código Javascript responsável por assistir o model e alterar o DOM quando algo mudar.

var output = document.querySelector('[my-output]');   
var modelProperty = output.getAttribute('my-output');         
model.watch(modelProperty, function (prop, oldValue, value) { 
output.innerHTML = value;
});

Como se pode ver no código a cima, a única coisa que mudou foi a utilização do método watch, que rodará o callback cada vez que a propriedade “name” do Model mudar seu valor.

Agora cada vez que você digitar algo no elemento contendo o atributo my-input, o mesmo valor será refletido no html do elemento contendo o atributo my-output!

É só isso?!

Sim, realmente é bem simples implementar um Two Way Data Binding. Lógico que esse código criado pode ser melhorado e muito! Mas o foco aqui, é manter a simplicidade para o entendimento geral de como as coisas funcionam.


No meu Github contém o repositório com esse tutorial simplificado e refatorado caso seja útil para algo.

Recomende isso para mais alguém, se você gostou. É sempre bom compartilhar conhecimento!

Muito obrigado e por hoje é isso :)