Framework Alpinejs
Alpinejs é um framework Javascript para adicionar comportamento diretamente nas marcaçõoes HTML. Ele se apresenta como sendo o jQuery para a web morderna. E realmente é uma ferramenta muito interessante. Tendo uma baixa curva de aprendizagem é muito bom para a criação de pequenos componentes dentro de uma página.
Para começar devemos incluí-lo em nosso documento.
<script defer src="https://unpkg.com/alpinejs@3.9.0/dist/cdn.min.js"></script>
Também podemos utilizar via npm
:
npm install alpinejs
//script.js
import Alpine from 'alpinejs'
window.Alpine = Alpine
Alpine.start()
O Alpinejs tem como core o state, que são os dados(objeto) javascript que ele observa por mudanças. Definimos o state através da directiva x-data
, dentro de uma marcação HTML. Dentro desta marcação podemos acessar e modificar o state do componente.
<div x-data="{count: 0}">
<button x-text="count" @click="count++"></button>
</div>
No exemplo acima definimos nosso state como um objeto javascript com o atributo count
valendo 0
. Dentro desta marcação criamos um elemento button
e nele incluimos uma directiva do alpinejs chamada x-text
, que recebe um valor(tipicamente do state) e o exibe como o valor de texto do elemento. Também utilizamos uma outra directiva do alpinejs o @click
que executa o conteúdo passado para ela quando o elemento onde ela esta sofre um evento de click, no caso somamos 1 no atributo do state do componente. Lembrando que o alpinejs fica observando mudanças em seu state, então ao alterar o atributo o texto do button
automaticamente será modificado na exibição. Veja o exemplo.
Para componentes mais complexos que não é viável ser colocado diretamente na marcação podemos passar uma função que retorna um objeto para a directiva x-data
.
<script>
window.contador = function(){
return{
count: 0,
incrementar: function(){
this.count++
}
}
}
</script>
<div x-data="contador()">
<button x-text="count" @click="incrementar()"></button>
</div>
Directivas do Alpinejs
O Alpinejs oferece diversas directivas para alterar o DOM em um documento.
x-text e x-html
Já vimos a directiva x-text
que serve para exibir o valor como valor de texto de uma tag. Ele aceita como valor qualquer expressão javascript.
<div x-data="{title: 'Um titulo'}">
<h1 x-text="title"></h1>
<div x-text="1+2"></div>
<div x-text="title+' da página'"></div>
</div>
No exemplo acima será exibido como um titulo ‘Um titulo’ que é o valor do atributo title, depois dentro do primeiro div o valor 3, que é o resultado da expressão 1+2
e no segundo div o texto ‘Um titulo da página’ que é o resultado da concatenação do atributo title com a string ‘ da página’.
A directiva x-html
funciona de forma semelhante, com a diferença que ela altera o innerHTML
do elemento.
<div x-data="{tag: '<h1>teste</h1>'}">
<div x-text="tag"></div>
<div x-html="tag"></div>
</div>
No exemplo acima o div com o x-text
irá escapar as tags html já no div com x-html
ele irá interpretar as tags normalmente sendo exibido a palavra teste como um título de nível 1.
x-show e x-if
A directiva x-show
é utilizada para mostrar ou ocultar um elemento conforme algum teste. É normalmente utilizado para criar modals, dropdowns, etc.
<div x-data="{open: false}">
<button @click="open = !open">Expandir</button>
<div x-show="open">
Conteúdo a ser exibido ....
</div>
</div>
Quando o valor de open é true ele irá mostar o div ‘Conteúdo a ser exibido ….’, caso seja false o div ficará oculto. Por baixo dos panos o alpinejs utiliza a propriedade CSS display: none;
para ocultar o elemento. Veja um exemplo.
A directiva x-if
serve para os mesmos fins que o x-show
, mas ao contrário de x-show que simplesmente oculta via CSS, o x-if
remove o elemento do DOM. Por este motivo que devemos inseri-lo através de uma marcação template
em vez de diretamente no elemento desejado.
<div x-data="{open: false}">
<button @click="open = !open">Expandir</button>
<template x-if="open">
<div>Conteúdo a ser exibido ....</div>
</template>
</div>
Veja o exemplo.
x-model
A directiva x-model
é utilizada para ligar um campo de formulário com um dado do state.
<form x-data="{nome: '',sobrenome:''}">
<div>
<label for="nome">Nome: </label>
<input type="text" name="nome" x-model="nome">
</div>
<div>
<label for="sobrenome">Sobrenome: </label>
<input type="text" name="sobrenome" x-model="sobrenome">
</div>
<div>
<div>Saída: </div>
<div>Nome: <span x-text="nome"></span></div>
<div>Sobrenome: <span x-text="sobrenome"></span></div>
</div>
</form>
No exemplo acima temos no state os valores nome e sobrenome que ligamos aos campos de formulário input
através da directiva x-model
. Assim quando o valor do input
for alterado também será alterado o valor no atributo associado no state. Veja o exemplo.
Esta ligação é feita nas duas vias se o atributo no state for alterado o valor do campo input também será.
<div x-data="{texto: ''}">
<div>
<input type="text" name="texto" x-model="texto">
</div>
<button @click="texto +='A'">A</button>
<button @click="texto +='B'">B</button>
<button @click="texto +='C'">C</button>
</div>
Acima vemos um campo input ligado ao atributo texto e 3 botões cada um com um evento de click que ao ser executado altera do valor do atributo concatenando uma letra a ele e em consequência o valor do input também. Veja o exemplo.
x-for
Podemos criar elementos no DOM iterando em um lista, para isto utilizamos a directiva x-for
. Ela é utilizada dentro de uma marcação template
que só deve ter um elemento com filho.
<div x-data="{nomes: ['Rodrigo','Angela','Carlos','Adalberto']}">
<ul>
<template x-for="nome in nomes">
<li x-text="nome"></li>
</template>
</ul>
</div>
Veja o exemplo.
x-bind
A directiva x-bind
permite que o valor de algum atributo do elemento HTML seja o valor de alguma expressão javascript. Para isto colocamos a directiva x-bind
antes do nome do atributo que queremos utilizar, por exemplo: x-bind:placeholder="textoPlaceholder"
.
Podemos utilizar uma versão curta do x-bind
que consiste em somente colocar os :
antes do atributo.
<div x-data="{disable: true}">
<form>
<input type="text" name="nome" :disabled="disable">
</form>
<button @click="disable= false">Habilitar</button>
<button @click="disable= true">Desabilitar</button>
</div>
No exemplo acima criamos um elemento input com seu atributo disabled
ligado com o valor do atributo disable do state. Usamos os botões para mudar o atributo do state disable e em resposta o campo input terá seu atributo alterado habilitado e desabilitando o campo para edição. Veja o exemplo.
A directiva x-bind
é muito utilizada para alterar as classes CSS de elementos conforme o state do componente.
<style>
.red{
border: 1px solid #F00;
}
</style>
<div x-data="{nome: ''}">
<form>
<input type="text" x-model="nome" :class="nome == '' ? 'red': '' ">
</form>
</div>
Utilizamos a directiva x-bind
no atributo class fazendo uso do operador ternário onde se o state nome for vazio então o class terá valor red senão o class ficará vazio. Veja o exemplo.
A directiva x-bind
também permite informar em seu valor um objeto javascript onde o nome do atributo é uma classe CSS que queremos utilizar e seu valor é um booleano, quando o valor do atributo é verdadeiro o alpinejs aplica a classe no elemento, se for falso não aplica.
<style>
.background{
background: #F00;
}
.border{
border: 2px solid #888;
}
.rounded{
border-radius: 30px;
}
</style>
<div x-data="{backgroundData: false, borderData: true, roundedData: false}">
<div style="width:200px;height:200px" :class="{background: backgroundData, border: borderData, rounded: roundedData}">
</div>
<div>
<input type="checkbox" x-model="backgroundData" id="backgroundData">
<label for="backgroundData">Background</label>
</div>
<div>
<input type="checkbox" x-model="borderData" id="borderData">
<label for="borderData">Border</label>
</div>
<div>
<input type="checkbox" x-model="roundedData" id="roundedData">
<label for="roundedData">Bordas Redondas</label>
</div>
</div>
No exemplo acima criamos um div de 200×200 e associamos as classes CSS: background, border e rounded através do x-bind
com os valores do seu state que são booleanos, então ao mudar o valor destes atributos no state(fazemos isso através dos inputs) as classes são aplicas ou não no elemento. Veja o exemplo.
Também temos um formato para utilizar o x-bind
com o atributo style, podemos passar para :style
um objeto javascript onde os nomes das propriedas do objeto e seus valores são as propriedades e valores do CSS.
<div x-data="{}">
<div :style="{ color: 'red', display: 'flex' }"></div>
</div>
<!-- Vai renderizar: -->
<div style="color: red; display: flex;" ...>
Eventos
O alpinejs utiliza a directiva x-on
: para definir um evento, após os dois pontos colocamos o evento que desejamos manipular, por exemplo, x-on:click
, x-on:change
, x-on:submit
, x-on:keyup
, x-on:keydown
. Também podemos utilizar uma versão mais curta(inclusive é que utilizamos anteriormente) que consiste em utilizar um @
antes da directiva, por exemplo, @click
, @change
, @submit
, @keyup
.
Dentro do valor da directiva de evento inserimos o código que queremos que seja executado quando o evento ocorrer, como se fosse o conteúdo da função passada para o listener. Podemos acessar o objeto do evento através da variável $event
.
<div x-data="{nomes: []}">
<select @change="nomes.push($event.target.value)">
<option value="Ana">Ana</option>
<option value="Maria">Maria</option>
<option value="João">João</option>
<option value="Fabricio">Fabricio</option>
</select>
<ul>
<template x-for="nome in nomes">
<li x-text="nome"></li>
</template>
</ul>
</div>
No exemplo acima definimos que no evento change iremos pegar do objeto do evento o elemento que sofreu o evento $event.target
e pegar o seu value
, e depois adicionar ao array nomes do state. Veja o exemplo.
Modificadores de Eventos
O alpinejs fornece diversos modificadores de eventos para customizar seu comportarmento. Entre eles temos.
.prevent: é o equivalente a chamar .preventDefault()
dentro de um listener de evento.
<div x-data="{}">
<form action="/teste" @submit.prevent="alert('não enviado')">
<input type="text" name="nome">
<input type="submit" value="Enviar">
</form>
</div>
Veja o exemplo.
.outside:
torna o evento de click para fora do elemento, ou seja, é disparado quando acontece um click fora do elemento que ele esta.
<div x-data="{alvo: ''}">
<div
@click="alvo='click dentro'"
@click.outside="alvo='click fora'"
x-text="alvo"
style="width: 200px; height: 200px; background: #CCC"
></div>
</div>
Veja o exemplo.
.window
: utilizando o modificador .window irá registrar o evento para todo objeto window em vez de somente para o próprio elemento.
<div x-data="{texto: ''}">
<div @keyup.window="texto += $event.key" x-text="texto"></div>
</div>
No exemplo acima irá registra o evento keyup para o window capturando os eventos de teclado de toda a página. Veja o exemplo.
Os eventos de keyup
e keydown
possuiem modificadores próprios para facilitar a detecção de algumas teclas especificas.
.shift | Tecla Shift |
.enter | Tecla Enter |
.space | Tecla de Espaço |
.ctrl | Tecla Control |
.cmd | Tecla Cmd |
.meta | Cmd no Mac, Control no Windows |
.alt | Tecla Alt |
.up .down .left .right | Teclas de seta para cima, baixo esquerda e direita |
.escape | Tecka Esc. |
.tab | Tecla Tab |
.caps-lock | Caps Lock |
x-ref
A directiva x-ref
é utilizada para acessar elemento do DOM de forma mais fácil sem precisar utilizar os getElementById
ou querySelector
. Podemos recupear o elemento utilizando a variável $ref.<valor_da_directiva>
<div x-data="{}">
<button @click="$refs.texto.remove()">Remover texto</button>
<span x-ref="texto">Um texto</span>
</div>
Veja o exemplo.
x-init
A directiva x-init
é utilizada para executar algo na inicialização do componente, como fazer uma busca em um API por exemplo. Caso o objeto do state tiver um método init ele irá ser executado.
<div x-data="{}" x-init="alert('Inicializando o componente!')">
</div>
<div x-data="{
init() {
alert('Inicializando o componente!')
}
}">
</div>
Veja o exemplo.
$watch
Usamos o método $watch
para observar um atributo do state e realizar alguma ação quando ele for modificado. Passamos de parâmetro o nome do atributo que queremos observar e a função a ser executada quando este for alterado.
<script>
function component(){
return {
texto: '',
init: function(){
let _this = this;
this.$watch('texto', function(){
if( _this.texto == "Boteco Digital" ){
alert("Obrigado por digitar 'Boteco Digital'")
}
})
}
};
}
</script>
<p>Digite "Boteco Digital"</p>
<div x-data="component()">
<input type="text" x-model="texto">
</div>
No exemplo acima como o código ficaria meio grande para ser colocado inline foi criado uma função que retorna o objeto do state. Nela temos o atributo texto que será associado com o input. Também criamos o método init() que será chamado na inicialização do componente, nele chamamos o método $watch()
, para observar alterações no atributo texto, quando ela ocorrer a função passada para o $watch
será executada comparando o texto com o valor esperado e mostrando um alert se for verdadeiro.
Veja o exemplo.
$dispatch
O método $dispatch
é utilizado para enviar um evento, este evento pode ser tratado utilizando a directiva x-on:
ou @
.
<div x-data="{}" @notificacao="alert('Evento disparado!!!')">
<button @click="$dispatch('notificacao')">
Notificar
</button>
</div>
Veja o exemplo.
Podemos enviar um evento para um outro componente utilizando o modificar de evento .window
que faz a directiva de evento observar os eventos de todo o navegador.
O método $dispatch
também permite que seja enviado um objeto junto com o evento, isso é feito passando um objeto javascript como segundo argumento do método, e estará disponível no handler do evento através de $event.detail
.
<div x-data="{}">
<button @click="$dispatch('notificacao',{msg: 'Um evento aconteceu!!!'})">
Notificar
</button>
</div>
<div x-data="{mensagem: ''}" @notificacao.window="mensagem=$event.detail.msg">
<div x-text="mensagem"></div>
</div>
Veja o exemplo.
Bom pessoal, espero que tenham gostado desta introdução, e como sempre mais detalhes de uma olhada na documentação,
T++