Kotlinautas
Esse conteúdo é oferecido e distribuído pela comunidade Kotlinautas, uma comunidade brasileira que busca oferecer conteúdo gratuito sobre a linguagem Kotlin em um espaço plural.
O quê é Kotlin/JS?
Com Kotlin/JS podemos escrever um código totalmente em Kotlin, e esse código em Kotlin será transformado em Javascript. Com isso, poderemos criar uma página web, com estrutura (HTML), estilos (CSS) e interação (Javascript) unicamente com Kotlin.
Uma das vantagens do Kotlin/JS é poder usar bibliotecas multi-plataforma dentro do Kotlin/JS, aumentando as combinações entre bibliotecas que podem ser feitas.
O quê é KVision?
KVision é um framework para a plataforma Kotlin/JS. Com KVision poderemos escrever código do Kotlin/JS de maneira mais simples, criando componentes, usando Bootstrap, estilizando elementos HTML com Kotlin,etc. Uma outra funcionalidade é usar componentes React/Redux dentro do KVision.
Além disso, KVision pode se integrar facilmente com Ktor, Spring, Quarkus e outros frameworks para Kotlin.
Materiais
Será necessário ter o IntelliJ instalado na máquina, conhecimento básico sobre a linguagem Kotlin e conhecimento básico sobre frontend (HTML, CSS e Javascript).
Instalando o plugin do KVision
Agora, vamos começar a criar o projeto, primeiro, vamos ao marketplace de extensões do IntelliJ. Vá ao menu de configurações, com o atalho Ctrl+Alt+S
, e ao menu Plugins:
Após isso, vá na barra de pesquisa e pesquise por kvision
. Com isso, o plugin do KVision irá aparecer e você poderá instalar clicando no botão Install
Agora, caso você clique no botão New Project, terá um novo menu no canto esquerdo, sendo o menu do KVision que acabamos de instalar.
Criando um projeto com KVision
Agora vamos criar um projeto com KVision. Primeiro, observe que o menu do KVision tem alguns campos, sendo:
Project Type: Define o tipo de projeto que será criado, podendo ser um projeto Ktor, Spring, Quarkus,etc. No caso, será apenas um projeto de frontend, então deixe na opção padrão Frontend project
GroupId: Define o grupo do pacote que será criado, esse campo é totalmente livre. Você pode colocar algo como com.kvsion
ArtifactId: Define o artifact do pacote que será criado, esse campo é totalmente livre. Você pode colocar algo como kvision
Kotlin/JS compiler: Define qual será o compilador que vamos usar no projeto. Deixe como está, que é o IR.
Opitional Modules: São diversos módulos que podem ser instalados de maneira opicional, primeiramente, vamos selecionar os dois primeiros, sendo o Bootstrap based components, e o Standard Bootstrap CSS styling
Após fazer essas configurações, clique no botão Next para continuar.
Agora preencha o nome, e a localização do projeto, sendo de escolha completamente pessoal. Caso não tenha nenhuma ideia, pode nomear com algo como kvision ou kvisiondemo por exemplo.
Caso você crie o projeto e dê algum erro dizendo que a configuração da JDK do Gradle é inválida, dessa maneira (texto e imagem):
Texto
Invalid Gradle JDK configuration found. Open Gradle Settings
Use JDK from project structure
Imagem
Para resolver isso, clique no botão Open Gradle Settings
, e irá aparecer o menu de configurações do Gradle
Vá á opção Gradle > Use Gradle from:
e mude essa opção de 'gradle-wrapper.properties' file
para 'wrapper' task in Gradle build script
.
Caso a opção abaixo Gradle JVM
esteja em vermlho, mude para uma versão válida. Clicando será possível de escolher uma versão da JVM específica para esse projeto.
Clique em OK para aplicaras mudanças. Com isso, as dependências do seu projeto serão carregadas no projeto.
Entendendo a estrutura de pastas do KVision
Os arquivos dentro da raiz do projeto são referentes á configuração do projeto e do KVision. Esses não iremos mexer em nada por enquanto.
Dentro da pasta src
temos todos os arquivos fonte da nossa aplicação, primeiramente temos duas pastas, sendo a main
que guarda o código principal da nossa organização, e a test
que irá guardar os testes da nossa aplicação.
Dentro da main
, temos apenas duas pastas, kotlin
que irá armazenar apenas código Kotlin. Caso nosso projeto tivesse Java (que não é o caso) teriamos uma pasta Java também. A outra pasta é a web
que guarda arquivos que serão usados por toda a aplicação. Agora temos apenas o arquivo index.html
, que guarda um template HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>KVision Template</title>
<script type="text/javascript" src="main.bundle.js"></script>
</head>
<body>
<div id="kvapp"></div>
</body>
</html>
A nossa aplicação está dentro de src/main/kotlin/com/kvision/kvision/App.kt
, que por enquanto apresenta apenas um Hello World. Vamos ver mais sobre esse arquivo:
package com.kvision.kvision
import io.kvision.Application
import io.kvision.CoreModule
import io.kvision.BootstrapModule
import io.kvision.BootstrapCssModule
import io.kvision.html.div
import io.kvision.module
import io.kvision.panel.root
import io.kvision.startApplication
class App : Application() {
override fun start() {
root("kvapp") {
div("Hello world")
// TODO
}
}
}
fun main() {
startApplication(
::App,
module.hot,
BootstrapModule,
BootstrapCssModule,
CoreModule
)
}
- Linha 3 á 10 importa diversos componentes, classes, elementos HTML,etc que vamos usar na nossa aplicação;
- Linha 12 declara uma classe que irá representar a nossa aplicação;
- Linha 13 - declara a função
start
, que irá guardar o código dessa página web em específica; - Linha 14 -
root
é uma função que cria um novo container. Esse container irá armazenar todas as tags HTML da aplicação, apenas precisamos informar um ID que é o ID do elemento que irá guardar todos esses elementos. No caso sendokvapp
; - Linha 15 - cria um elemento
div
que apenas está escrevendo umhello world
na tela. Servindo apenas como exemplo; - Linha 21 - declara a função
main
da nossa aplicação, sendo essa a função principal; - Linha 22 - Inicia a aplicação com a função
startApplication
; - Linha 24 á 27 - São passados os módulos que baixamos para a aplicação, sendo o
module.hot
um módulo que nos permite mudar uma página e automaticamente a mudança ocorrer no navegador,BootstrapModule
eBootstrapCssModule
que são módulos relacionados á Bootstrap, e oCoreModule
que é um módulo padrão do KVision;
Para iniciar a aplicação, clique na barra lateral Gradle, depois em Run Configurations, e em Run run duas vezes, para assim fazer que a aplicação seja iniciada na URL localhost:3000
Agora nossa aplicação está inciada, e na página localhost:3000 irá aparecer o Hello World do KVision.
Agora vamos fazer um exercício bem simples, vamos mudar o texto de hello world
para Olá, mundo!
. Isso pode ser feito mudando o conteúdo da função div
:
class App : Application() {
override fun start() {
root("kvapp") {
div("Olá, mundo!")
}
}
}
- Mudamos o conteúdo de dentro de
div
e também removemos o comentário// TODO
;
Agora, o novo conteúdo será automaticamente atualizado e mostrado na página.
Criando elementos HTML
Agora, vamos ver alguns exemplos de elementos HTML que podem ser criados usando KVision.
Primeiro, vamos modificar uma importação do nosso código. Pode ser visto na linha 7 que importamos apenas o elemento div
:
import io.kvision.html.div
Vamos mudar esse import, para ao invés de importar apenas o elemento div
, importar todos os elementos HTML suportados pelo KVision, e mais algumas funcionalidades relacionadas á CSS e JS. Isso pode ser feito utilizando o caractere coringa *
:
import io.kvision.* // Funções, classes,etc. do KVision
import io.kvision.core.* // Funcionalidades relacionadas á CSS e JS
import io.kvision.html.* // Todas as tags HTML
import io.kvision.panel.* // Importar todos os painéis que podem ser criados (veremos mais adiante)
import io.kvision.utils.* // Unidades de medida como px (pixel)
Listas
Uma lista em HTML é uma série de dados unidos em uma forma visual de uma lista, um exemplo de lista é:
- Primeiro elemento
- Segundo elemento
- Terceiro elemento
Isso pode ser feito em HTML com dois elementos, sendo <ul>
, que é uma lista não ordenada, e <li>
que é um elemento de uma lista. Logo, em HTML a lista acima seria:
<ul>
<li>Primeiro elemento</li>
<li>Segundo elemento</li>
<li>Terceiro elemento</li>
</ul>
Isso pode ser feito no KVision usando a função listTag
, que representa uma lista em HTML.
na função listTag
, iremos precisar informar o tipo da lista, sendo ul
para listas não ordenadas (só com as bolinhas por exemplo) e ol
para listas ordenadas, e após isso informar a lista. Um exemplo prático disso é esse:
...
class App : Application() {
override fun start() {
root("kvapp") {
listTag(ListType.UL, listOf("Primeiro elemento", "Segundo elemento", "Terceiro elemento"))
}
}
}
...
- Informamos o tipo da lista usando o método
listType.UL
, caso quisessemos que essa lista fosse uma<ol>
, apenas iriamos mudar paralistType.OL
; - Após isso, passamos uma lista de strings usando a função
listOf
, colocando os elementos da lista dentro;
Com isso, a lista será mostrada na página.
Caso mudemos o argumento ListType.UL
para listType.OL
, com o código ficará dessa maneira:
...
class App : Application() {
override fun start() {
root("kvapp") {
listTag(ListType.OL, listOf("Primeiro elemento", "Segundo elemento", "Terceiro elemento"))
}
}
}
...
A lista ficará ordenada na página, seguindo assim a mudança feita de lista não ordenada para lista ordenada.
Links
No HTML, para criar links usamos a tag <a>
, que representa uma "âncora" que cria um link para uma página. No caso da tag <a>
vamos precisar informar um parametro href
, que é para onde aquele link irá levar, e também um texto ou outros elementos dentro da tag <a>
. Dessa maneira:
<a href="https://dev.to/kotlinautas">Ver artigos da Kotlinautas</a>
Para criar links no KVision podemos usar a função link
, passando um placeholder, que é um texto que será clicável, e o link. Dessa maneira:
...
class App : Application() {
override fun start() {
root("kvapp") {
link("Ver artigos da Kotlinautas", "https://dev.to/kotlinautas")
}
}
}
...
Agora teremos um texto clicável em nossa página, que quando é clicado levará á lista de artigos da Kotlinautas.
Quando o link é clicado, a página atual é substuida pela lista de artigos da Kotlinautas. Como posso mudar esse comportamento, e fazer que quando o link é clicado, seja criada uma nova página com a página do link?
Olhando para a assinatura da função link
, podemos ver todos os argumentos que podem ser passados:
fun Container.link(
label: String,
url: String? = null,
icon: String? = null,
image: ResString? = null,
separator: String? = null,
labelFirst: Boolean = true,
target: String? = null,
className: String? = null,
init: (Link.() -> Unit)? = null
): Link
Podemos ver que os únicos argumentos que usamos foram o label
, que é o texto do link, e o url
que é para onde o link está redirecionando. O argumento que precisamos adicionar para mudar o comportamento de redirecionamento desse link é no target
. Isso pode ser feito passando esse target na chamada dessa função link
, dessa maneira:
...
class App : Application() {
override fun start() {
root("kvapp") {
link("Ver artigos da Kotlinautas", "https://dev.to/kotlinautas", target = "_blank")
}
}
}
...
- Passamos o target diretamente, usando o
target =
, e passando o valor_blank
que irá fazer que uma nova página seja aberta.
Conteúdo dinâmico
Podemos mudar o conteúdo de uma página dependendo de alguma interação que a pessoa usuária da página fizer. Isso pode ser feito usando a função .onEvent
, que irá executar algo se algum evento específico, como um clique, o mouse passar por cima do elemento,etc. acontecer.
Vamos ver o exemplo abaixo:
...
class App : Application() {
override fun start() {
root("kvapp") {
link("Link para o Twitter da Kotlinautas", "https://twitter.com/kotlinautas").onEvent {
mouseover = {
self.label = "Link para o Twitter da Feministech"
self.url = "https://twitter.com/feminis_tech"
}
}
}
}
}
...
- Temos um elemento
link
que leva ao twitter da Kotlinautas; - Usamos a função
.onEvent
, iniciando um bloco onde podemos colocar os eventos que podem ocorrer com esse link; - Colocamos um evento dentro desse bloco, sendo o
mouseover
, que é um evento que ocorre toda vez que o mouse passa por cima do elemento; - Dentro desse
mouseover
, mudamos o texto e a url do link usando a variávelself
que representa o elemento;
Agora, quando você passar o mouse pelo link que levava ao twitter da Kotlinautas, o link será automaticamente modificado, e irá te enviar ao twitter da Feministech no lugar.
Há outros eventos que podem ser colocados no lugar, caso queira ver todos que podem ser usados, veja nessa lista da MDN
Rich Text
Podemos inserir um texto com tags HTML como seu conteúdo no KVision. Veja no exemplo abaixo:
...
class App : Application() {
override fun start() {
root("kvapp") {
p(
"<strong>Texto em negrito</strong>"
)
}
}
}
...
Quando você abrir a página, o conteúdos será um texto <strong>Texto em negrito</strong>
:
Isso aconteceu pois o texto na página está sendo mostrado apenas como texto, não como tags HTML. Para fazer que um texto seja interpretado como HTML, podemos passar um argumento chamado rich
como verdadeiro. Dessa maneira:
...
class App : Application() {
override fun start() {
root("kvapp") {
p(
"<strong>Texto em negrito</strong>",
rich = true
)
}
}
}
...
Agora, o texto mostrado na página será interpretado como HTML:
Criando componentes
Um componente é como se fosse uma tag HTML criada por nós mesmos. Onde podemos informar seu conteúdo, criar um estilo personalizado, misturar uma ou mais tags dentro de uma única,etc.
Primeiro, vamos criar um novo arquivo em src/main/kotlin/com/kvision/kvision
chamado Cartão.kt
. Esse arquivo terá algumas importações:
package com.kvision.kvision
import io.kvision.core.*
import io.kvision.html.*
import io.kvision.utils.*
Depois, vamos criar uma função chamada Cartão
que será o nosso componente. A ídeía é criar um texto em negrito, com um fundo cinza. Formando como se fosse um retângulo. Primeiro, vamos criar a função:
fun Container.Cartão(texto: String? = null): Strong {
}
- Essa interface
Container
foi usada pois todo componente (e tag HTML no KVision) precisa estar dentro dessa interface para ter alguns métodos e propriedades disponíveis; - Recebemos uma variável
texto
, que será o conteúdo do componente; - o retorno
: Strong
deixa claro que o elemento que iremos retornar será um elemento em negrito (<strong></strong>
)
Após isso, vamos criar o elemento:
fun Container.Cartão(texto: String? = null): Strong {
val elemento = Strong(content = texto, className = "cartão")
}
- Usamos o método
Strong()
, que irá criar por sua vez, um elemento HTML<strong>
- Passamos apenas dois argumentos, sendo um
content
que é o conteúdo do elemento, no caso será a variáveltexto
. E umclassName
que representa o nome da classe que poderá eventualmente ser usado em um arquivo CSS ou JS; - Guardamos tudo isso em uma variável chamada
elemento
;
Agora, vamos fazer algumas modificações no estilo desse elemento, para criar assim o estilo de um cartão:
fun Container.Cartão(texto: String? = null): Strong {
val elemento = Strong(content = texto, className = "cartão")
elemento.background = Background(Color("#DDD"))
elemento.padding = 10.px
elemento.fontSize = 30.px
}
- Modificamos o estilo do elemento acessando diretamente essas propriedades, usando
.background
,.padding
,etc. e definindo o valor dessas variáveis; - Para definir o background, usamos dois métodos, sendo o
Background
, que irá retornar o background, e umColor
que irá retornar uma cor. Dentro do color passamos a cor em forma de hexadecimal, sendo#DDD
; - Para definir valores em pixel, inserimos um número, seguido de um
.px
indicando a unidade. Caso quissemos usar outra unidade comovh
ouvw
, apenas mudariamos o final, ficando10.vw
por exemplo;
Agora vamos terminar a função adicionando esse elemento ao Cartão e retornando esse elemento:
fun Container.Cartão(texto: String? = null): Strong {
val elemento = Strong(content = texto, className = "cartão")
elemento.background = Background(Color("#DDD"))
elemento.padding = 10.px
elemento.fontSize = 30.px
this.add(elemento)
return elemento
}
Pronto, agora já temos o componente pronto.
Agora podemos usar o nosso componente Cartão
dessa maneira:
...
class App : Application() {
override fun start() {
root("kvapp") {
Cartão("Testando a criação de componentes")
}
}
}
...
- Como você pode observar, usamos a função
Cartão
como qualquer elemento HTML do KVision. Com esse código, a nossa página ficará assim:
Estilizando a nossa página
Agora vamos começar a estilizar a nossa página, adicionando CSS usando o próprio KVision como meio para criar esse CSS.
Primeiro, vamos mudar a página para algo mais simples, que apenas mostra diversos textos em tamanhos diferentes e com tags diferentes:
...
class App : Application() {
override fun start() {
root("kvapp") {
h1("Texto maior")
h2("Texto menor")
strong("texto em negrito")
br()
i("texto em itálico")
}
}
}
...
- Criamos um título com
h1
, um subtítulo comh2
, um texto em negrito comstrong
, quebramos a linha usando obr
(Break Line), e ao final inserimos um texto em itálico comi
.
Agora, vamos criar um arquivo chamado estilo.kt
em src/main/kotlin/com/kvision/kvision
. Esse arquivo irá armazenar os estilos que iremos aplicar.
Primeiro, vamos importar o KVision nesse arquivo:
package com.kvision.kvision
import io.kvision.core.*
import io.kvision.utils.*
Agora vamos inserir primeiro o estilo do h1
. Isso pode ser feito definindo uma variável que irá armazenar esse estilo, usando uma classe Style
, e dentro dessa classe iremos colocar os estilos. Isso pode ser feito da seguinte forma:
package com.kvision.kvision
import io.kvision.core.*
import io.kvision.utils.*
val estiloH1 = Style {
color = Color("blue")
}
- Usamos a classe
Style
, e dentro dela determinamos que a cor do texto desse estilo fosse azul, mudando a variávelcolor
, atribuindo com o retorno de uma função chamadaColor
, que gera uma cor baseada em um texto (código hexadecimal, nome,etc.).
Agora, vamos voltar ao arquivo App.kt
e vamos adicionar esse estilo ao nosso h1. Isso pode ser feito da seguinte forma:
...
class App : Application() {
override fun start() {
root("kvapp") {
h1("Texto maior") { addCssStyle(estiloH1) }
h2("Texto menor")
strong("texto em negrito")
br()
i("texto em itálico")
}
}
}
...
- Adicionamos ao corpo dessa função
h1
, a funçãoaddCssStyle
. Que permite a adição de estilos ao elemento apenas informando a variável que está guardando o estilo, no caso sendo aestiloH1
.
Agora a nossa página está com o h1 estilizado com a cor azul, dessa maneira:
Podemos agora seguir o mesmo padrão e estilizar cada elemento que criamos. Tente criar estilos para o h2
, strong
e i
sem ajuda primeiramente.
Caso tenha ficado com algum problema, ou não teve idéias de como estililzar esses elementos, você pode seguir o exemplo abaixo de como ficaria o arquivo estilo.kt
ao final:
package com.kvision.kvision
import io.kvision.core.*
import io.kvision.utils.*
val estiloH1 = Style {
color = Color("blue")
}
val estiloH2 = Style {
background = Background(Color("#DDD"))
}
val estiloStrong = Style {
color = Color("green")
}
val estiloI = Style {
padding = 40.px
}
- No
estiloH2
usamos a funçãobackground
para gerar um background para o elemento. Esse background no caso é umColor
, que representa uma cor. Essa cor sendo#DDD
que é um cinza bem claro. - No
estiloStrong
deixamos a cor do texto verde. O método foi o mesmo que usamos para oestiloH1
; - No
estiloI
, temos apenas um padding de 40 pixels, usando o método de colocar um número, um.
e a unidade de medida;
Agora apenas precisamos aplicar esses estilos na página. Podemos fazer isso da mesma forma que fizemos com o h1
:
class App : Application() {
override fun start() {
root("kvapp") {
h1("Texto maior") { addCssStyle(estiloH1) }
h2("Texto menor") { addCssStyle(estiloH2) }
strong("texto em negrito") { addCssStyle(estiloStrong) }
br()
i("texto em itálico") { addCssStyle(estiloI) }
}
}
}
Pronto, agora nossa página terá vários elementos com vários estilos diferentes:
Botões
Para criar um botão no KVision, podemos usar a função button
e informar qual será o texto do botão, como no exemplo abaixo:
...
class App : Application() {
override fun start() {
root("kvapp") {
button("Botão feito com KVision")
}
}
}
...
Com esse exemplo acima, o código gerado será:
Podemos criar um botão com um estilo diferente, como um botão primário, segundário, botão de perigo,etc. Podemos mudar esse estilo passando um argumento style
ao botão. Dessa maneira:
...
class App : Application() {
override fun start() {
root("kvapp") {
button("Salvar alterações", style = ButtonStyle.DANGER)
}
}
}
...
Informando o style
sendo ButtonStyle.DANGER
vamos criar um botão que representa uma ação perigosa, que deve ser tomada com cuidado,etc. Ficando dessa maneira na tela:
Podemos também inserir uma ação que será feita quando esse botão for clicado. Isso pode ser feito adicionando um bloco onClick
para a função button
. Dessa maneira:
...
class App : Application() {
override fun start() {
root("kvapp") {
button("Salvar alterações", style = ButtonStyle.DANGER) {
onClick {
println("Alterações salvas")
}
}
}
}
}
...
- Dentro do
onClick
, apenas mostramos no console que a alteração foi salva (apenas para ilustrar a funcionalidade). Isso pode ser feito usando a funçãoprintln
que nesse contexto, irá mostrar algo no console do navegador.
Há diversos estilos de botões que podem ser usados no KVision, sendo a lista completa sendo:
- PRIMARY
- SECONDARY
- SUCCESS
- INFO
- WARNING
- DANGER
- LINK
- LIGHT
- DARK
- OUTLINEPRIMARY
- OUTLINESECONDARY
- OUTLINESUCCESS
- OUTLINEINFO
- OUTLINEWARNING
- OUTLINEDANGER
- OUTLINELIGHT
- OUTLINEDARK
Tente mudar o estilo do botão que criamos se baseando na lista acima como exercício.
Containers de Layout
Agora vamos usar um recurso chamado Containers de Layout (Layout Containers), que são tags do KVision que criam div's com um comportamento diferente, como por exemplo uma div onde os elementos dentro dela podem ser modificados em seu tamanho. Ou uma div onde cada elemento representa uma aba,etc.
Vamos ver por exemplo o splitPanel
. Essa função irá criar um painel que o tamanho das áreas de dentro desse painel podem ser reajustadas pelo usuário. Esse painel pode ser criado da seguinte forma:
...
class App : Application() {
override fun start() {
root("kvapp") {
splitPanel {
div("Primeira área")
div("Segunda área")
}
}
}
}
...
- Usamos o
splitPanel
como se fosse uma tag do KVision; - Dentro dela, inserimos duas div's apenas para demonstrar o funcionamento, contendo apenas um texto;
Com o código acima, a nossa página ficará assim:
Essa barra vertical pode mudar o tamanho de cada seção desses elementos, criando mais interação com a pessoa usuária.
Podemos também criar um Tab Panel que é um layout em abas, mostrando um elemento filho por vez. Pode ser criado dessa maneira:
...
class App : Application() {
override fun start() {
root("kvapp") {
tabPanel {
tab("Primeira aba") {
div("Conteúdo da primeira aba")
}
tab("Segunda aba") {
div("Conteúdo da segunda aba")
}
tab("Terceira aba") {
div("Conteúdo da terceira aba")
}
}
}
}
}
...
- A função usada para criar o painel é a
tabPanel
, onde iremos colocar os elementos do painel dentro; - Cada aba do painel é criada usando a função
tab
, que representa a aba;
Com esse código, o resultado será:
Há outros painéis que podem ser usados no KVision, mas esses dois são ótimos exemplos.
Finalização
Nesse artigo vimos algumas funcionalidades interessantes do KVision, e como criamos HTML, CSS e Javascript com Kotlin. Tente criar um site simples usando KVision, como um portifólio ou algo do tipo.
Muito obrigada por ler ❤️🏳️⚧️ e me segue nas redes, é tudo @lissatransborda 👀
Top comments (2)
Kotlin faz tudo
I don't understand much but the article looks great :-) Thanks for promoting KVision! :-)