Desenvolvimento

13 set, 2016

Como construir a sua primeira aplicação com Elm  – Parte 01

Publicidade

No meu último artigo, Elm: Programação Funcional no Front-End do jeito certo, falei sobre as principais características e vantagens da linguagem mas (praticamente) sem mostrar código. Ou seja, dei ênfase no porquê e não no como. Hoje, vou focar no como e mostrar na prática o passo a passo para criar uma aplicação bem simples com Elm.

Introdução

Neste artigo, não vamos fazer um setup da linguagem, mas se você deseja ter o Elm instalado e poder criar suas próprias aplicações, sugiro seguir o guia oficial.

Vamos construir uma aplicação bem simples, mas que demonstra diversos aspectos da linguagem: um contador.

elm-1Contador simples

Na documentação do Elm, podemos ver um exemplo bem parecido.

Modularização

Para importarmos módulos com Elm, basta adicionarmos import seguido do nome do módulo que desejamos. Como vamos utilizar HTML na aplicação, vamos importar o módulo Html, um dos módulos oficiais da linguagem, assim:

import Html

Dessa forma podemos invocar funções do módulo Html:

Html.text 'Olá'

Mas repetir o nome do módulo toda vez que formos invocar uma função dele pode ser cansativo. Podemos evitar essa repetição alterando o import, expondo as funções que estamos usando:

import Html exposing (text)
text 'Olá'

Podemos também expor todas as funções de um módulo, sem precisar nomear cada uma delas:

import Html exposing (..)
text 'Olá'

Com isso, já temos a primeira linha da nossa aplicação:

import Html exposing (..)

Model

O nosso model será extremamente simples. Como temos um contador, o modelo será um valor inteiro simples, inicializado com zero:

model = 0

Opcionalmente, podemos deixar explícita a tipagem do modelo, fazendo uma anotação de tipo (ou Type Annotation), desta forma:

model: Int
model = 0

Se não fizermos a anotação de tipo, o compilador irá automaticamente inferir os tipos.

Com isso, nossa aplicação está assim:

import Html exposing (..)
model: Int
model = 0

View

Não faz sentido construir um contador sem que seja possível visualizá-lo. Precisamos então da nossa view, que será simplesmente uma função que converterá código Elm em HTML.

Para refrescar a memória, é disto que precisamos:

elm-2

Ou seja, dois botões: um para incrementar e um para decrementar, e um elemento de texto com o valor do contador.

Podemos então implementar a função que irá representar a view desta forma:

view model =
  div []
    [ button [] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [] [ text "+" ]
    ]

O código acima pode parecer complicado, mas vamos desmitificá-lo passo a passo.

1. view model =
2.   div []
3.     [ button [] [ text "-" ]
4.     , div [] [ text (toString model) ]
5.     , button [] [ text "+" ]
6.     ]

Na linha 1, estamos criando uma função chamada view, que recebe como parâmetro o nosso model.

Essa nova função view receberá uma div, que também é uma função (linha 2):

1. view model =
2.   div []
3.     [ button [] [ text "-" ]
4.     , div [] [ text (toString model) ]
5.     , button [] [ text "+" ]
6.     ]
  1. A função div recebe dois parâmetros:
    O primeiro é uma lista de atributos (id, class, style etc). No nosso caso, ela vai ficar vazia porque não precisamos de nenhum atributo.
  2. E o segundo é uma lista de elementos filhos dessa div.
1. view model =
2.   div []
3.     [ button [] [ text "-" ]
4.     , div [] [ text (toString model) ]
5.     , button [] [ text "+" ]
6.     ]

Os filhos da div (da linha 2) serão:

  1. Um botão para decrementar o contador (linha 3)
  2. Uma outra div com o valor do contador (linha 4)
  3. Um botão para incrementar o contador (linha 5)

Como o nosso model é um Int, não podemos simplesmente usá-lo na função text, porque ela espera uma String como parâmetro. Por isso, convertemos o valor do model de um Int para uma String:

1. view model =
2.   div []
3.     [ button [] [ text "-" ]
4.     , div [] [ text (toString model) ]
5.     , button [] [ text "+" ]
6.     ]

Agora basta explicitarmos as anotações de tipo da view. Se analisarmos a função view, verificamos que ela espera um model como parâmetro (que é simplesmente um Int) e retorna um Html como resultado. Isso resultaria em:

view: Int -> Html
view model =
  div []
    [ button [] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [] [ text "+" ]
    ]

Porém, isso está incorreto por um pequeno detalhe:

view: Int -> Html Msg

Mais pra frente, vamos entender esse Msg obscuro, mas quero que neste momento você entenda apenas que a view recebe o model e retorna um Html.

Portanto, nossa aplicação completa se encontra desta maneira:

import Html exposing (..)

model: Int
model = 0

view: Int -> Html Msg
view model =
  div []
    [ button [] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [] [ text "+" ]
    ]

Type Aliases

Uma boa convenção da comunidade Elm é criar Type Aliases para facilitar a leitura das anotações de tipo criadas.

No nosso caso, podemos criar um Alias para o modelo desta forma:

type alias Model = Int

Ou seja, em todos os lugares da nossa aplicação que estamos usando o Int para nos referir ao model, podemos agora usar o próprio Model. Facilita muito a leitura, principalmente em aplicações grandes.

Atualizando então a aplicação, temos:

import Html exposing (..)

type alias Model = Int
model: Model
model = 0

view: Model -> Html Msg
view model =
  div []
    [ button [] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [] [ text "+" ]
    ]

Ficou alguma dúvida? Calma que ainda temos a parte 2! Na próxima semana, eu volto com o final do artigo sobre como criar uma aplicação em Elm. Se você tiver alguma sugestão ou comentário, aproveite os campos abaixo.