<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Fernando Raposo da Camara Silva</title>
    <description>The latest articles on Forem by Fernando Raposo da Camara Silva (@ferfox1981).</description>
    <link>https://forem.com/ferfox1981</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F618555%2Ff3335d28-6e72-48b4-949c-a477d1e1d831.jpeg</url>
      <title>Forem: Fernando Raposo da Camara Silva</title>
      <link>https://forem.com/ferfox1981</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ferfox1981"/>
    <language>en</language>
    <item>
      <title>Docker + VSCode to Easily Set Up Dev Environment</title>
      <dc:creator>Fernando Raposo da Camara Silva</dc:creator>
      <pubDate>Mon, 30 Aug 2021 22:55:16 +0000</pubDate>
      <link>https://forem.com/ferfox1981/docker-vscode-to-easily-set-up-dev-environment-2b8i</link>
      <guid>https://forem.com/ferfox1981/docker-vscode-to-easily-set-up-dev-environment-2b8i</guid>
      <description>&lt;p&gt;You've already gone through this: You're going to start with a project and to do so, you'll have to go through the journey that is to configure the entire development environment. Download and install Dev IDE,required libraries, necessary tools... Ask one guy, ask another one... Until 8 hours later (hopefully) you finally managed to get the environment up.&lt;br&gt;
Docker together with a VSCode extension called Remote Development can facilitate and speed up the installation of these environments, even if the dependency stack is large.&lt;br&gt;
This article will be divided into 3 parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Docker + VSCode + Remote Development extension;&lt;/li&gt;
&lt;li&gt;Set up a development environment with a large dependency stack;&lt;/li&gt;
&lt;li&gt;Test Effectiveness.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Docker + VSCode + Remote Development Extension
&lt;/h2&gt;

&lt;p&gt;Docker is a powerful tool, I've already written about it &lt;a href="https://dev.to/ferfox1981/using-docker-em-app-web-spring-boot-4e4o"&gt;here&lt;/a&gt; (in Portuguese), with it you can create different types of environment isolated from a host machine. To install Docker enter &lt;a href="https://www.docker.com/get-started" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remote Development Extension
&lt;/h3&gt;

&lt;p&gt;This extension allows a file on the host computer to be opened inside a Container, either on a remote machine or in &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/" rel="noopener noreferrer"&gt;WSL&lt;/a&gt; if you are on Windows. What are the benefits of this?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Develop on the same operating system where the system will be deployed, or use faster and more specialized hardware than what is on your local machine. - Keep in mind that a Docker Container may be running on your machine locally, or anywhere in the world. So, if you have a slow computer, but someone provides you a external more "powerful" container, it can even reduce costs for companies that instead of providing high-end computers for their employees, could provide a more modest (and cheaper configuration) and focus on providing the development Containers.&lt;/li&gt;
&lt;li&gt;Fasten the learning curve of new employees by standardizing   the creation of development environments (as the little story I told at the beginning).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although the first topic is an almost limitless subject, it is also complex, so in this article I will focus on the second topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up a development environment with a large dependency stack;
&lt;/h2&gt;

&lt;p&gt;The preconditions for creating this environment are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Have Docker and VSCode installed;&lt;/li&gt;
&lt;li&gt;Add the Remote Development extension in VSCode;&lt;/li&gt;
&lt;li&gt;Have the need to create a specific development environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To install Docker and VSCode just go to the links that was already presented. Once the VSCode is open, go to install an extension (CTRL+Shift+X) called Remote Development, as seen in the figure below.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbngmmu6id00foyed1pr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbngmmu6id00foyed1pr.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Next, let's think about a development environment that has dependencies that we don't have originally on the host machine, or that are in different versions than those needed for development. It could be a specific version of JAVA, but I thought of something more complex to test the "limits" of this approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development Stack
&lt;/h3&gt;

&lt;p&gt;Let's imagine that we are going to develop a mobile App, using Ionic. To run Ionic, we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node (latest version)&lt;/li&gt;
&lt;li&gt;Angular (latest version)&lt;/li&gt;
&lt;li&gt;Ionic (latest version)
Let's see how my local machine is:
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkm1nqfoe3qkqdsselg9.png" alt="image"&gt;
As can be seen, Ionic is outdated (it says that there is a newer version), Angular is also old (in version 10), as well as Node (which is in v10.17 when there is v14 by any less). Okay, am I going to spend precious time trying to update all this? NOT! Even because it may be the case that other projects I'm working on need these apparently outdated dependencies.
### Putting Dependency Stack on a Container
The first step we have to do is open a folder in VSCode and write a Dockerfile describing the to-do items that need to be installed in our development environment, whether they are: Node (and npm), Angular and Ionic. And let's run all of this inside Alpine which is a very small version of Linux. The Dockerfile might look like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM alpine:3.14

WORKDIR "/home"

RUN apk add --update nodejs npm

RUN npm install -g @angular/cli

RUN npm install -g @ionic/cli

CMD [""]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keeping in mind that this folder where the Dockerfile is saved will be opened inside a Container with the dependencies that are described in it, click on the green button on the left side of the VSCode. An option box will open and from the existing ones choose "Open Folder In Container..."&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnv7wl3fh4ofozyg1jvo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnv7wl3fh4ofozyg1jvo.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Then what happens is that the VSCode and the extension will download the image, create the Container and leave it running ready to start the work.&lt;br&gt;
NOTE: Yes, this process can take a few minutes depending on your internet connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Effectiveness
&lt;/h2&gt;

&lt;p&gt;After the time of creating the Container and installing the dependencies, the result will look something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feq72lo7b0z7emuu6ni8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feq72lo7b0z7emuu6ni8g.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Let's test it in the Container's terminal to see if the dependencies are different from the host:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbnznjldl6kd8x4be5js2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbnznjldl6kd8x4be5js2.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Everything seems to be in agreement, one important thing to remember is that there is now a Docker Container running under the hood, you can check this with the command&lt;br&gt;
&lt;code&gt;$docker ps&lt;/code&gt;&lt;br&gt;
there will be a line like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fva7402q5tr3dhxdu1dz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fva7402q5tr3dhxdu1dz9.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Closing VSCode will not close the Container, it will be running until you finish it!&lt;br&gt;
That's it, you can start creating your Ionic project, just type&lt;br&gt;
&lt;code&gt;$ionic start&lt;/code&gt;&lt;br&gt;
And start making the App with the dependencies you want, and if any of your colleagues need the same thing, just send him the Dockerfile you have.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Docker + VSCode para Montar Ambientes de Desenvolvimento Facilmente</title>
      <dc:creator>Fernando Raposo da Camara Silva</dc:creator>
      <pubDate>Sat, 28 Aug 2021 15:47:31 +0000</pubDate>
      <link>https://forem.com/ferfox1981/docker-vscode-para-montar-ambientes-de-desenvolvimento-facilmente-33fe</link>
      <guid>https://forem.com/ferfox1981/docker-vscode-para-montar-ambientes-de-desenvolvimento-facilmente-33fe</guid>
      <description>&lt;p&gt;Você já passou por isso: Vai iniciar em um projeto e para tal, terá que passar pelo caminho das pedras que é configurar todo o ambiente de desenvolvimento. Baixar e instalar a IDE de dev, bibliotecas diversas, ferramentas necessárias... Pergunta para um, pergunta para outro até que 8 horas depois (com sorte), finalmente conseguiu levantar o ambiente.&lt;br&gt;
Pois o Docker em conjunto com uma extensão do VSCode chamada Remote Development pode facilitar e agilizar a instalação destes ambientes, mesmo se a pilha de dependências grande.&lt;br&gt;
Este artigo vai ser dividido em 3 partes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Docker + VSCode + Extensão Remote Development;&lt;/li&gt;
&lt;li&gt;Criar Ambiente de desenvolvimento com uma pilha de dependências;&lt;/li&gt;
&lt;li&gt;Testar Efetividade da solução.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Docker + VSCode + Extensão Remote Development
&lt;/h2&gt;

&lt;p&gt;O Docker é uma ferramenta poderosa, já escrevi sobre ela &lt;a href="https://dev.to/ferfox1981/utilizando-docker-em-app-web-spring-boot-4e4o"&gt;aqui&lt;/a&gt;, com ela você consegue criar diversos tipos de ambiente de forma isolada em uma máquina hospedeira. Para instalar o Docker entre &lt;a href="https://www.docker.com/get-started" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;. &lt;br&gt;
O &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VSCode&lt;/a&gt; é ultimamente uma das IDEs mais populares para desenvolvimento de software, sendo leve, gratuito e intuitivo, além de ter diversas extensões para facilitar a vida enormemente. Ele está sendo o que o &lt;a href="https://www.eclipse.org/" rel="noopener noreferrer"&gt;Eclipse&lt;/a&gt; foi uns anos atrás (não que o Eclipse não seja legal também!). Uma extensão do VSCode que me chamou a atenção foi a &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack" rel="noopener noreferrer"&gt;Remote Development&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remote Development Extension
&lt;/h3&gt;

&lt;p&gt;Esta extensão permite que um arquivo no computador hospedeiro seja aberto dentro de um Container, ou em uma máquina remota ou no &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/" rel="noopener noreferrer"&gt;WSL&lt;/a&gt; caso você esteja no Windows. Quais os benefícios disso?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desenvolver no mesmo sistema operacional em que se implantará o sistema, ou utilizar hardware mais rápido e especializado do que o que está na sua máquina local. - Tenha em mente que o Container do Docker pode estar rodando na sua máquina de forma local, ou em qualquer lugar do mundo. Assim, se você tem um computador meio fraquinho, mas alguém te prover este container mais "poderoso" isso pode até reduzir os custos das empresas que ao invés de proverem computadores topo de linha para seus funcionários, poderiam prover uma configuração mais modesta (e barata) e focar em prover os Containers de desenvolvimento.&lt;/li&gt;
&lt;li&gt;Acelerar novos membros da equipe a se tornarem mais produtivos padronizando ambientes de desenvolvimento mais uniformes e estruturados (conforme a historinha narrei no início).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apesar do primeiro tópico ser um assunto quase ilimitado, ele também é complexo, assim neste artigo vou focar no segundo tópico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando Ambiente de Desenvolvimento Padronizado
&lt;/h2&gt;

&lt;p&gt;As precondições para a criação deste ambiente são:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ter o Docker e o VSCode instalados;&lt;/li&gt;
&lt;li&gt;Adicionar no VSCode a extensão Remote Development;&lt;/li&gt;
&lt;li&gt;Ter a necessidade de criar um ambiente de desenvolvimento específico.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Para instalar o Docker e  o VSCode basta ir nos links já passados anteriormente. Uma vez com o VSCode aberto, busque e instale uma extensão (CTRL+Shift+X) que se chama Remote Development, como visto na figura abaixo.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbngmmu6id00foyed1pr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbngmmu6id00foyed1pr.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
A seguir vamos pensar em um ambiente de desenvolvimento que tenha dependências que não temos originalmente na máquina host, ou que estejam em versões diferentes das necessárias para o desenvolvimento. Poderia ser uma versão específica de JAVA, mas pensei em algo mais complexo para testarmos os "limites" desta abordagem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pilha de Desenvolvimento
&lt;/h3&gt;

&lt;p&gt;Vamos imaginar que vamos desenvolver um App mobile, utilizando o Ionic. Para rodar o Ionic, precisamos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node (versão mais recente)&lt;/li&gt;
&lt;li&gt;Angular (versão mais recente)&lt;/li&gt;
&lt;li&gt;Ionic (versão mais recente)
Vamos ver como está a minha máquina local:
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkm1nqfoe3qkqdsselg9.png" alt="image"&gt;
Como pode ser visto, o Ionic está defasado (ele mesmo diz que  há uma versão mais recente), o Angular também está antigo (na versão 10), assim como o Node (que está na versão v10.17 quando já há a v14 pelo menos). Certo, vou gastar tempo precioso tentando atualizar tudo isso? NÃO! Até por que pode ser que outros projetos que estou trabalhando precisem destas dependências aparentemente defasadas.
### Colocando Pilha de Dependências em um Container
O primeiro passo que temos que fazer é abrir uma pasta no VSCode e escrever um arquivo Dockerfile descrevendo as pendências que precisam ser instaladas no nosso ambiente de desenvolvimento, sejam elas: Node (e npm), Angular e Ionic. E vamos rodar tudo isso dentro do Alpine que é uma versão bem pequena do Linux. O Dockerfile pode ser assim:
```
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FROM alpine:3.14&lt;/p&gt;

&lt;p&gt;WORKDIR "/home"&lt;/p&gt;

&lt;p&gt;RUN apk add --update nodejs npm&lt;/p&gt;

&lt;p&gt;RUN npm install -g @angular/cli&lt;/p&gt;

&lt;p&gt;RUN npm install -g @ionic/cli&lt;/p&gt;

&lt;p&gt;CMD [""]&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tendo em mente que esta pasta em que o Dockerfile está salvo será aberta dentro de um Container com as dependências que estão descritas nele, clique no botão verde que fica no lado esquerdo do VSCode. Uma caixa de opções será aberta e dentre as existentes escolha "Open Folder In Container..."
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wnv7wl3fh4ofozyg1jvo.png)
Depois o que acontece é que o VSCode e a extensão tratarão de  baixar a imagem, criar o Container e deixá-lo rodando pronto para o início do trabalho.
OBS: Sim, este processo pode levar alguns minutos a depender da sua conexão de internet. 

## Testando Efetividade
Depois do tempo de criação do Container e instalação das dependências, o resultado será mais ou menos este:
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eq72lo7b0z7emuu6ni8g.png)
Vamos testar no terminal do Container para ver se as dependências estão diferentes das do host:
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bnznjldl6kd8x4be5js2.png)
Parece que está tudo de acordo, uma coisa importante é que lembre-se que há agora por baixo dos panos um Container Docker rodando, você pode comprovar isso com o comando 
`$ docker ps`
haverá uma linha assim:
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/va7402q5tr3dhxdu1dz9.png)
Fechar o VSCode não vai encerrar o Container, ele ficará rodando enquanto você não terminá-lo!
É isso, você pode começar a criar o seu projeto Ionic, basta digitar
`$ionic start`
E começar a fazer o App com as dependências que quiser, e se algum colega seu precisar da mesma coisa, é só mandar pra ele o Dockerfile que você tem.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>docker</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Utilizando Docker em App WEB Spring Boot </title>
      <dc:creator>Fernando Raposo da Camara Silva</dc:creator>
      <pubDate>Mon, 16 Aug 2021 22:51:38 +0000</pubDate>
      <link>https://forem.com/ferfox1981/utilizando-docker-em-app-web-spring-boot-4e4o</link>
      <guid>https://forem.com/ferfox1981/utilizando-docker-em-app-web-spring-boot-4e4o</guid>
      <description>&lt;p&gt;Certo, muito se fala hoje em dia em Docker... A minha experiência recente é de puro fascínio, como demorei tanto para utilizá-lo? Realmente não sei... &lt;br&gt;
Neste artigo tentarei sintetizar meus entendimentos de Docker e como utilizá-lo para "rodar" um sisteminha Web bem básico. Assim divido tudo em partes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Conceito do Docker e o que ele tenta resolver;&lt;/li&gt;
&lt;li&gt;Um pequeno sistema WEB utilizando Spring Boot;&lt;/li&gt;
&lt;li&gt;Juntando tudo: o sistema WEB rodando dentro do Docker;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  O que é o Docker?
&lt;/h2&gt;

&lt;p&gt;Analise estes cenários:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lembra aquela vez em que você queria usar um aplicativo no seu computador e instalando dependências necessárias para tal acabou por "quebrar" outros aplicativos no computador?&lt;/li&gt;
&lt;li&gt;Ou quando para evitar esse tipo de coisa descrita acima você tentou levantar um outro Sistema Operacional virtualizado rodando por cima do seu S.O e no final tudo isso rodando junto ficou tão lento e ocupou tanto espaço que você desistiu!&lt;/li&gt;
&lt;li&gt;Lembra aquele sistema que você desenvolveu, roda legal na sua máquina mas quando você coloca em produção você passa a noite inteira para fazer funcionar?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para facilitar a resolução dos três cenários acima a resposta é Docker, Docker e Docker! Vamos primeiro tentar entender a diferença entre um sistema rodando no Docker e rodando numa virtualização de sistema operacional olhando a figura abaixo:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc1cri7osbt8sibkdse8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc1cri7osbt8sibkdse8.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para entender Docker precisamos entender o conceito de Containers. Pelo próprio &lt;a href="https://www.docker.com/resources/what-container#:~:text=A%20container%20is%20a%20standard,one%20computing%20environment%20to%20another.&amp;amp;text=Secure%3A%20Applications%20are%20safer%20in,isolation%20capabilities%20in%20the%20industry" rel="noopener noreferrer"&gt;site&lt;/a&gt; do Docker, um container é: &lt;em&gt;"Uma peça padrão de software que empacota código e suas dependências de forma que as aplicações rodem rapidamente e de forma confiável de um ambiente computacional para o outro."&lt;/em&gt; Neste &lt;a href="https://www.simplilearn.com/tutorials/docker-tutorial/docker-vs-virtual-machine" rel="noopener noreferrer"&gt;site&lt;/a&gt; há uma comparação legal, que compara o Docker a um condomínio de apartamentos e um sistema virtualizado a uma casa alugada.&lt;br&gt;
Enquanto que em um condomínio os recursos (a piscina, a academia, garagem, água...) são compartilhados entre os vizinhos. Em uma casa alugada nada é compartilhado, ou seja tudo é exclusivo, e sabemos que essa exclusividade tem um &lt;strong&gt;custo&lt;/strong&gt;. &lt;br&gt;
Resumindo: Containers são menores que imagens virtuais, podem ser mais facilmente construídos (e destruídos) e eles compartilham recursos com o S.O em que estão rodando. Em contrapartida, sistemas virtualizados não compartilham nada um com o outro e também não compartilham recursos no S.O em que estão rodando.&lt;/p&gt;

&lt;p&gt;OBS: Informações sobre como instalar o Docker podem ser encontradas no &lt;a href="https://docs.docker.com/get-docker/" rel="noopener noreferrer"&gt;site oficial&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Docker
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1.1. Dockerfile
&lt;/h2&gt;

&lt;p&gt;O Docker entende uma receitinha de bolo que explica como construir o Container, essa receita é um arquivo sem terminação chamado Dockerfile. Se você vai usar um Linux bem pequeno chamado alpine para rodar o seu programa, você tem que dizer isso no Dockerfile. Se vai precisar instalar uma ferramenta/ dependência que o seu sistema precisa dizer isso também no Dockerfile. &lt;/p&gt;

&lt;h2&gt;
  
  
  1.2 Docker Image
&lt;/h2&gt;

&lt;p&gt;O Dockerfile é só a receita do Container. É necessário construí-lo fisicamente em uma &lt;em&gt;imagem&lt;/em&gt; (na verdade aquele Linux chamado Alpine que é pequeno e que você pode usar também é uma imagem), ou seja, imagens específicas são compostas de outras mais genéricas.&lt;/p&gt;

&lt;h2&gt;
  
  
  1.3 Container
&lt;/h2&gt;

&lt;p&gt;Depois que temos o Dockerfile e a imagem construída, colocamos o Container baseado naquela imagem para rodar. Se fizermos a analogia com JAVA, imagine o Dockerfile como se fosse o arquivo *.java, a imagem como se fosse o *.class ou o *. jar gerado e o Container como o aquivo jar rodando. E como sabemos, para rodar um jar muitas vezes precisamos passar parâmetros, com os Containers não é diferente, por exemplo, se queremos acessar uma porta do Container, precisamos passar isso como parâmetro.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Sistema WEB com SpringBoot
&lt;/h1&gt;

&lt;h2&gt;
  
  
  2.1. &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Crie uma pasta chamada docker e abra o VSCode nela e pressione CTRL+SHIFT+p&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$mkdir docker
/docker$ code .


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Escolha Spring Initializr: Create a Maven Project&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzuja2rcr40ek9lqfghdn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzuja2rcr40ek9lqfghdn.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Depois escolha a versão mais recente que houver do SpringBoot, no caso, estou usando 2.5.3&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faam9knjjveiu27nf8g8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faam9knjjveiu27nf8g8c.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Escolha a linguagem JAVA e mantenha as opções que vem sendo apresentadas (com.example) e (demo). No packaging type, escolha Jar e na versão JAVA eu estou trabalhando com a 8.&lt;br&gt;
Por fim escolha apenas a dependência do Spring Web (a última da foto)&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpj6f1p60t6uwx9w84dq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpj6f1p60t6uwx9w84dq.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
 Após isso o seu VSCode deve estar assim com a classe DemoApplication.java criada:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0hsi1hx794tv0h82255.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0hsi1hx794tv0h82255.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
 O programa ainda não tem muita função, precisamos de um acesso para este retorne informações quando o sistema receber requisições externas. Vamos criar uma classe chamada Serviço (Servico.java) dentro de uma package chamada service que é bem simples, ela só retorna "Hello World":&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package com.example.demo.service;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Servico {

    @RequestMapping("/hello")
    public String hello() {
        return "Hello World";
    }

}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Volte na classe DemoApplication e no método main clique em Run para executar a aplicação. &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0trawx83qgwud52fzp9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0trawx83qgwud52fzp9.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
 Quando ela acabar de levantar, vá no browser e escreva &lt;a href="http://localhost:8080/hello" rel="noopener noreferrer"&gt;http://localhost:8080/hello&lt;/a&gt;&lt;br&gt;
O resultado será o abaixo, e isto quer dizer que o seu sistema WEB está rodando localmente com acesso ao serviço /hello na porta 8080.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqksnwi0mx4jd4pmtfk9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqksnwi0mx4jd4pmtfk9.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Falamos antes de Docker e agora temos uma aplicação WEB rodando. Como criar um Container rodando esta aplicação? É o próximo desafio.&lt;/p&gt;
&lt;h1&gt;
  
  
  3. Aplicativo Rodando no Container
&lt;/h1&gt;
&lt;h2&gt;
  
  
  3.1. Construindo Dockerfile
&lt;/h2&gt;

&lt;p&gt;Temos o nosso aplicativo construído na seção 2, vamos agora pensar em como seria o ambiente para executá-lo. Primeiramente, vamos executá-lo em um Container Linux, então vamos considerar o Alpine, mais informações sobre ele &lt;a href="https://www.alpinelinux.org/" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;. Lembrem que eu escolhi o Java 8 quando estava criando o aplicativo? Então este é outro ponto a se considerar.&lt;br&gt;
Crie um arquivo Dockerfile (sem extensão) no mesmo diretório criado (docker) e no mesmo local onde o projeto JAVA está criado e irei comentar linha a linha este arquivo Dockerfile. &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Linha 1: Diz que precisaremos de uma imagem do Linux Alpine e que deve vir com um jdk versão 8 já instalado (prático, não precisamos instalar JAVA);&lt;br&gt;&lt;br&gt;
Linha 3: Diz qual será o diretório de trabalho no Container, no caso será o &lt;code&gt;/home&lt;/code&gt;;&lt;br&gt;&lt;br&gt;
Linha 5: Diz para copiar &lt;em&gt;tudo&lt;/em&gt; que estiver neste diretório em que estamos e mandar para o WORKDIR definido (no caso &lt;code&gt;/home&lt;/code&gt;);&lt;br&gt;&lt;br&gt;
Linha 7: Como a versão Alpine do Linux é bem básica, precisamos instalar o Maven (lembrem que criamos um Maven Project lá no VSCode), é isto que este comando faz;&lt;br&gt;&lt;br&gt;
Linha 9: Após a linha 3 executar passamos a ter um diretório &lt;code&gt;/demo&lt;/code&gt; dentro de &lt;code&gt;/home&lt;/code&gt;, setamos então &lt;code&gt;/home/demo&lt;/code&gt; como sendo o novo diretório de trabalho;&lt;br&gt;&lt;br&gt;
Linha 11: Rodamos o comando para fazer o MAVEN gerar o Jar do App que desenvolvemos, este jar é criado em uma pasta &lt;code&gt;/home/demo/target&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Linha 13: Este comando expõe a porta 8080 (que é a porta que o App Web utiliza para receber requisições&lt;br&gt;&lt;br&gt;
Linha 15: Este comando representa o que deverá ser rodado no prompt deste Container quando ele for iniciado, que são o comando java, com os parâmetros "-jar" e o arquivo jar a ser executado &lt;code&gt;/home/demo/target/demo-0.0.1-SNAPSHOT.jar&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3.2. Gerando Imagem
&lt;/h2&gt;

&lt;p&gt;Lembrem que o Dockerfile é como se fosse o arquivo .java, então temos que gerar o .jar dele para podermos rodá-lo. Para fazer isso, utilizamos o comando &lt;code&gt;build&lt;/code&gt; e com isso geraremos a imagem com tudo que está descrito no Dockerfile. Assim, na mesma pasta em que estão o Dockerfile e a pasta &lt;code&gt;/demo&lt;/code&gt; com o nosso projeto Spring, digite:&lt;br&gt;
&lt;code&gt;docker build . -t java-spring&lt;/code&gt;&lt;br&gt;
O que isso vai fazer? Vai ler o Dockerfile que está nesta pasta, vai ler o projeto Spring criado e gerar a imagem que terá o nome de "java-spring". Aguarde a imagem ser criada e depois digite o comando &lt;code&gt;docker image list&lt;/code&gt; para constatar que a imagem foi criada.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1kopo6v6p36fmvrh7sum.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1kopo6v6p36fmvrh7sum.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Isso quer dizer que a imagem (o nosso jar) foi criado. Temos que pô-lo para rodar.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.3. Criando Container
&lt;/h2&gt;

&lt;p&gt;Como foi dito, da mesma forma como temos que passar parâmetros para rodar um arquivo jar, para rodar um Container também temos a mesma lógica. Para executarmos o Container e conseguirmos acessá-lo do browser da mesma forma que acessamos quando rodamos localmente precisaremos fazer um mapeamento de portas. Recorde-se que na Linha 13 foi exposta a porta 8080, precisamos agora mandar informações para esta porta mapeando uma porta no S.O host para a porta do Container. Veja o comando abaixo para gerar o Container&lt;br&gt;
&lt;code&gt;docker run --name java-container -d -p 8080:8080 java-spring&lt;/code&gt;&lt;br&gt;
traduzindo os parâmetros para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--name&lt;/code&gt;: o nome do Container (java-container);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt;: Modo dettached (isso quer dizer que após o container começar a rodar, ele ficará rodando em background e o terminal ficará livre para o usuário);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p&lt;/code&gt;: é o mapeamento de portas PORTA_HOST:PORTA_CONTAINER, quer dizer que uma requisição no host para a porta 8080 irá ser enviada para o host na porta 8080.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O parâmetro a seguir é justamente a imagem &lt;code&gt;java-spring&lt;/code&gt; que foi criada, seria como se fosse o nome do jar que vamos rodar.&lt;/p&gt;

&lt;p&gt;Após solicitar que o Container inicie-se pode ir no Browser e digitar &lt;a href="http://localhost:8080/hello" rel="noopener noreferrer"&gt;http://localhost:8080/hello&lt;/a&gt;, o efeito será o mesmo de quando executávamos o app web no host, justamente a palavra Hello World.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.4. Comandos Adicionais Docker
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Listar Containers rodando
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;$docker ps&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Listar Containers existentes
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;$docker ps -a&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Iniciar um Container
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;$docker start &amp;lt;nome_container&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Derrubar um Container
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;$docker stop &amp;lt;nome_container&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Reiniciar um Container (stop seguido de um start)
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;$docker restart &amp;lt;nome_container&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Listar Imagens Máquina Local
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;$docker image list&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Remover Imagem
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;$docker rmi &amp;lt;nome_imagem&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Enviar um comando para um Container rodando
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;$docker exec -it &amp;lt;nome_container&amp;gt; &amp;lt;comando&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Considerações
&lt;/h1&gt;

&lt;p&gt;O Docker é um aliado poderoso, vale a pena aprender e usá-lo. O app e o Dockerfile estão &lt;a href="https://github.com/ferfox1981/docker-spring" rel="noopener noreferrer"&gt;aqui&lt;/a&gt; para quem quiser baixar.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>spring</category>
      <category>java</category>
    </item>
    <item>
      <title>Scrolling to an Element Only After It Appears using Angular</title>
      <dc:creator>Fernando Raposo da Camara Silva</dc:creator>
      <pubDate>Thu, 08 Jul 2021 00:51:45 +0000</pubDate>
      <link>https://forem.com/ferfox1981/scrolling-to-an-element-only-after-it-appears-using-angular-1g6m</link>
      <guid>https://forem.com/ferfox1981/scrolling-to-an-element-only-after-it-appears-using-angular-1g6m</guid>
      <description>&lt;p&gt;This is an evolution of my previous &lt;a href="https://dev.to/ferfox1981/tree-ways-to-scroll-to-an-element-using-angular-1dlj"&gt;article&lt;/a&gt;. Let's suppose you have the following requirement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In a long page, wait for a specific HTML Element to appear, and &lt;strong&gt;only&lt;/strong&gt; after its generation scroll to it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It looks simple right? But imagine that this Element exibition could take some time, for instance, it could be a grid with some information provided from a web service, or some data from a slow SQL query. Nevertheless, there's no reason to scroll before the data is already shown. So how can we do it? My goals are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a button that will generate a grid at the bottom of a long page;&lt;/li&gt;
&lt;li&gt;After the button is clicked, some mechanism is needed to simulate random time;&lt;/li&gt;
&lt;li&gt;Scroll to the grid &lt;strong&gt;only&lt;/strong&gt; after it was added to the page.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;comment&lt;/em&gt;: The &lt;a href="https://www.w3schools.com/html/html_tables.asp" rel="noopener noreferrer"&gt;table&lt;/a&gt; to be scrolled is not added to the page by default. This is possible by using a &lt;code&gt;*ngIf&lt;/code&gt; statement. As you can see bellow, this is achieved by setting the variable &lt;code&gt;showTable&lt;/code&gt; to false at startup. This DOM concept is important to understand, because if you have decided to use &lt;code&gt;hidden&lt;/code&gt; attibute instead of &lt;code&gt;*ngIf&lt;/code&gt; strategy, the table would be already on your page and DOM, the only thing is that it would be hidden.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d7uzlll57drnitrjasi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d7uzlll57drnitrjasi.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Button
&lt;/h4&gt;

&lt;p&gt;Let's create a button that will call a fake backend. Let's also add a Spinner just to illustrate time. &lt;a href="https://projects.lukehaas.me/css-loaders/" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is a good place where you can find cool CSS Spinners to add to your page.&lt;br&gt;
Bellow you can see that after clicking the button a function named &lt;code&gt;waitAndGoDown()&lt;/code&gt; is called. This will be described in details next.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;&amp;lt;div style="text-align: center"&amp;gt;&lt;br&gt;
  &amp;lt;button (click)="waitAndGoDown()"&amp;gt;Wait Random time and go Down&amp;lt;/button&amp;gt;&lt;br&gt;
  &amp;lt;p&amp;gt;&lt;br&gt;
  &amp;lt;div *ngIf="showSpinner" class="loader"&amp;gt;Loading...&lt;br&gt;
  &amp;lt;/div&amp;gt;&lt;br&gt;
&amp;lt;/div&amp;gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
&lt;br&gt;
  &lt;br&gt;
  

&lt;ol&gt;
&lt;li&gt;Fake Backend
&lt;/li&gt;
&lt;/ol&gt;
&lt;/h4&gt;


&lt;p&gt;By default, after clicking the button we want to turn the Spinner on and wait some random time until finally exibit the grid. A fake backend can be simulated by using a &lt;code&gt;setTimeout&lt;/code&gt; method. Look inside &lt;code&gt;waitAndGoDown()&lt;/code&gt; function:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55pm6ogqb5fifu29gxka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55pm6ogqb5fifu29gxka.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As it can be seen on &lt;a href="https://stackblitz.com/edit/wait-and-scroll?file=src%2Fapp%2Fapp.component.ts" rel="noopener noreferrer"&gt;Stackblitz&lt;/a&gt;, &lt;code&gt;simulateBackend()&lt;/code&gt; function uses a random &lt;code&gt;setTimeout&lt;/code&gt; limited to 5 seconds to randomize the return of the fake Backend. This means that after a while the Spinner is turned off and the grid is allowed to appear.&lt;br&gt;
&lt;em&gt;comment&lt;/em&gt;: Remember that everything is asynchronous, as a result, the program doesn't wait &lt;code&gt;simulateBackend&lt;/code&gt; to return to invoke &lt;code&gt;waitForElement&lt;/code&gt;. That's why there's a need for some mecanism to monitor when the table appears (or when the DOM mutates) and eventually when to scrool to it.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Monitoring the Grid
&lt;/h4&gt;

&lt;p&gt;Check bellow how the monitoring is done line by line, notice that the id &lt;code&gt;'myTable'&lt;/code&gt; of the table to be presented is passed as an argument.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6x8idxac0m9a9pknplx6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6x8idxac0m9a9pknplx6.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lines 39-43:&lt;/strong&gt; Checks if the element is already there. If it is, scroll to it and return.&lt;br&gt;
&lt;strong&gt;Line 44:&lt;/strong&gt; Creates an observer that monitors nodes added to the DOM. Every time the DOM mutates, the changes are observed.&lt;br&gt;
&lt;strong&gt;Lines 47-54:&lt;/strong&gt; It checks if the newest mutation contains the element we are looking for (the table!). If it is, scroll to it.&lt;br&gt;
&lt;strong&gt;Lines 56-59:&lt;/strong&gt; Defines what kind of nodes are going to be observed (the entire childList of the root component)&lt;/p&gt;

&lt;p&gt;The function that does the scrolling is one of the options presented &lt;a href="https://dev.to/ferfox1981/tree-ways-to-scroll-to-an-element-using-angular-1dlj"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There's also a &lt;a href="https://stackblitz.com/edit/wait-and-scroll?file=src%2Fapp%2Fapp.component.ts" rel="noopener noreferrer"&gt;Stackblitz&lt;/a&gt;  with this example. &lt;br&gt;
&lt;iframe src="https://stackblitz.com/edit/wait-and-scroll?" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;br&gt;
Hope this can help someone!&lt;/p&gt;

&lt;p&gt;Fonts:&lt;br&gt;
&lt;a href="https://projects.lukehaas.me/css-loaders/" rel="noopener noreferrer"&gt;https://projects.lukehaas.me/css-loaders/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://codepad.co/snippet/wait-for-an-element-to-exist-via-mutation-observer" rel="noopener noreferrer"&gt;https://codepad.co/snippet/wait-for-an-element-to-exist-via-mutation-observer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>html</category>
      <category>dom</category>
    </item>
    <item>
      <title>Google Maps on Your Ionic4 Project w/ Angular</title>
      <dc:creator>Fernando Raposo da Camara Silva</dc:creator>
      <pubDate>Fri, 25 Jun 2021 02:11:30 +0000</pubDate>
      <link>https://forem.com/ferfox1981/google-maps-on-your-ionic4-project-w-angular-48dj</link>
      <guid>https://forem.com/ferfox1981/google-maps-on-your-ionic4-project-w-angular-48dj</guid>
      <description>&lt;h1&gt;
  
  
  Ionic
&lt;/h1&gt;

&lt;p&gt;The advantage of &lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt; is that if you have knowlegde of some Web Development Framework (e.g.: Angular, React, Vue or pure Javascript), then you can start creating Cross-Platform Mobile Apps right away. This means a reduced learning curve and increased productivity.&lt;br&gt;
Nevertheless, some people may say that an Ionic App is not a native one, and also that it can generate an app that is slower than a "real" native one made with Flutter or Kotlin. Ok... But we cannot forget that phrase commonly used in informatics: "It really depends...". It depends on your team, it depends on your timeline, it also depends on the devices you will be running the apps.&lt;/p&gt;
&lt;h1&gt;
  
  
  Objectives
&lt;/h1&gt;

&lt;p&gt;My goals in this article are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up a project using Ionic 4 and Angular;&lt;/li&gt;
&lt;li&gt;Integrate Google Maps into the project;&lt;/li&gt;
&lt;li&gt;Exercise some Maps features like centering, maps inputs and outputs;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  1. Project Setup
&lt;/h3&gt;

&lt;p&gt;The basic dependencies to start your project are: Node.js and Angular. If you do not have Node.js, go &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. If you do not have Angular installed, go &lt;a href="https://angular.io/guide/setup-local" rel="noopener noreferrer"&gt;here&lt;/a&gt;. After installing both, you need to install Ionic. Just type:&lt;br&gt;
&lt;code&gt;npm install -g @ionic/cli&lt;/code&gt;&lt;br&gt;
or go &lt;a href="https://ionicframework.com/docs/intro/cli" rel="noopener noreferrer"&gt;here&lt;/a&gt; for further details.&lt;br&gt;
Finally, let's create our Ionic 4 project. Type:&lt;br&gt;
&lt;code&gt;ionic start&lt;/code&gt;&lt;br&gt;
and next select Angular as framework.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm80sv5yeauggyekro63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm80sv5yeauggyekro63.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Next, give a name to your project and as starter template choose sidemenu as seen bellow:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxhafmof61jj1be1g2yl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxhafmof61jj1be1g2yl.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Next, if a question: &lt;code&gt;"Integrate your new app with Capacitor to target native iOS and Android? (y/N)"&lt;/code&gt; is prompted, Choose (y) and wait until the template is completely generated.&lt;br&gt;
There is only one more dependency to be added and we are ready to go. Go to your project's folder and install this dependency by typing:&lt;br&gt;
&lt;code&gt;npm install @angular/google-maps&lt;/code&gt;&lt;br&gt;
Next type: &lt;code&gt;code .&lt;/code&gt; To open the project on VSCode, and, once inside it, type on terminal &lt;code&gt;ionic serve&lt;/code&gt; to check if our template is up and running. If everything went ok, you'll see at &lt;a href="http://localhost:8100" rel="noopener noreferrer"&gt;http://localhost:8100&lt;/a&gt; this image which emulates a mobile device on browser after pressing F12 key:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrvsk0v6k1qo5yhnikj3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrvsk0v6k1qo5yhnikj3.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Google Maps Integration
&lt;/h3&gt;

&lt;p&gt;Google Maps is just perfect! However, in order to use it integrated to an application we have to pay for it. There's no free lunch right? Google has detailed instructions about billing and how to use Maps API &lt;a href="https://developers.google.com/maps/gmp-get-started" rel="noopener noreferrer"&gt;here&lt;/a&gt;. After the payment process (do not worry you don't have to pay anything in advance) you'll receive an API KEY, which allows us to consume the Map services provided and billed by Google.&lt;/p&gt;
&lt;h4&gt;
  
  
  2.1 The App
&lt;/h4&gt;

&lt;p&gt;Let's consider the following scenario: We'll adapt our generated template to a tourism App that presents points of interest to tourists from Cruise Lines. Our App will show  points of interest near where the ship is anchored. Those points of interest will be divided in categories like (Restaurant, Must-See, Restroom, Tourist Info.).&lt;/p&gt;
&lt;h4&gt;
  
  
  2.2 Adaptations to Generated Sidemenu project
&lt;/h4&gt;

&lt;p&gt;We will use &lt;a href="https://github.com/angular/components/tree/master/src/google-maps" rel="noopener noreferrer"&gt;Google Maps Component&lt;/a&gt; to ease the integration. First, go to &lt;code&gt;index.html&lt;/code&gt; and&lt;br&gt;&lt;br&gt;
add the following script line:&lt;br&gt;
&lt;code&gt;&amp;lt;script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br&gt;
Keep in mind that you will have to use that API KEY   generated after Google's billing process is completed instead of the variable "YOUR_API_KEY".&lt;/p&gt;

&lt;p&gt;Next, we need do adapt the template to the tourism context. Notice that the generated template looks like a mail box, so let's change its context. Replace "Inbox" with "Welcome", "&lt;a href="mailto:hi@ionicframework.com"&gt;hi@ionicframework.com&lt;/a&gt;" with "&lt;a href="mailto:tourism@tourism.com"&gt;tourism@tourism.com&lt;/a&gt;", remove completely the Labels and adjust the itens and icons to present: All, Restaurant, Must-See, Restroom, Tourist Info.&lt;br&gt;
As a result, the App now looks like below:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux1y4e4nx6anhlq1ccys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux1y4e4nx6anhlq1ccys.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Go to Folder component, and on &lt;code&gt;folder.module.ts&lt;/code&gt; file add GoogleMapsModule to imports.&lt;/p&gt;

&lt;p&gt;Still, on Folder Component go to its template and inside the &lt;code&gt;div&lt;/code&gt; with &lt;code&gt;id=container&lt;/code&gt; replace the code with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;google-map
    height="500px"
    width="500px"
    &amp;gt;
    &amp;lt;/google-map&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, theoretically, Google Maps should appear like this on the app:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7o499aiapzv3qr426xn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7o499aiapzv3qr426xn.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Google Maps Features
&lt;/h3&gt;

&lt;p&gt;You can see on previous pictures that when google maps doesn't know where to center, it goes "home". That's why the project is centered on GooglePlex, California at first. In order to change centering to a certain place, you need to discover this place's latitude and longitude (just click on the map and the coordinates will appear as shown bellow):&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpw5lw9yz6rl94hu6agei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpw5lw9yz6rl94hu6agei.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Create on &lt;code&gt;folder.page.ts&lt;/code&gt; a variable &lt;code&gt;center&lt;/code&gt; and set longitude and latitude attributes like this:&lt;br&gt;
&lt;code&gt;center = new google.maps.LatLng(-8.063242, -34.871048);&lt;/code&gt;&lt;br&gt;
and update the template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;google-map
    height="700px"
    width="500px"
    [center]="center"
    &amp;gt;
    &amp;lt;/google-map&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can see that the map is centered according to the coordinates defined by &lt;code&gt;center&lt;/code&gt; variable.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.1 Points of Interest
&lt;/h4&gt;

&lt;p&gt;Now, let's define some points of interest. In order to do it we can use this &lt;a href="https://geojson.io/" rel="noopener noreferrer"&gt;tool&lt;/a&gt; to generate a list of points interest and also add meaningful data associated to it.&lt;br&gt;
For instance, if you click somewhere on the map, you can then add properties like a title and a category, and a json containing your definitions is generated on the right side.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fik5dhdcc1go6nm4u58ak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fik5dhdcc1go6nm4u58ak.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
Next, take the json points and create a file called points.json and import it on your file.&lt;br&gt;
A possible points.json file is shown next:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "marker-color": "#7e7e7e",
        "marker-size": "medium",
        "marker-symbol": "",
        "title": "Marco Zero",
        "cat": "mustsee"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -34.871112406253815,
          -8.063165383068121
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "marker-color": "#7e7e7e",
        "marker-size": "medium",
        "marker-symbol": "",
        "title": "Malakoff Tower",
        "cat": "mustsee"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -34.87082004547119,
          -8.060759318240265
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "marker-color": "#7e7e7e",
        "marker-size": "medium",
        "marker-symbol": "",
        "title": "Cais do Sertão Museum",
        "cat": "mustsee"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -34.87032651901245,
          -8.061216099860022
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "marker-color": "#7e7e7e",
        "marker-size": "medium",
        "marker-symbol": "",
        "title": "Kahal-Zur-Israel Sinagoge",
        "cat": "mustsee"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -34.87139403820038,
          -8.06174192922556
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          -34.871858060359955,
          -8.061085970265072
        ]
      }
    }
  ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition, to use the json file, go to &lt;code&gt;tsconfig.json&lt;/code&gt; file and on compilerOptions add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "resolveJsonModule": true, "esModuleInterop": true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this you'll be able to import the json file like this:&lt;br&gt;
&lt;code&gt;import points from './points.json'&lt;/code&gt;&lt;br&gt;
Finally, we have to show markers for the points we have defined. Markers are defined using the following component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;map-marker
    *ngFor="let marker of markers"
    [position]="marker.position"
    [label]="marker.label"
    [title]="marker.title"
    [options]="marker.options"
  &amp;gt;
  &amp;lt;/map-marker&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to filter each point of interest selected in order to show just some, or all the points. For instance, if we click on "All" or when opening the app at first time, the following points are shown:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1h1o8382x542m45i6m3e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1h1o8382x542m45i6m3e.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
However, if "Must See" is clicked, only those points are presented:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxhodknk6be6biieb19n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxhodknk6be6biieb19n.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the code is &lt;a href="https://github.com/ferfox1981/ionic-google-maps" rel="noopener noreferrer"&gt;here&lt;/a&gt; I hope this article help someone!&lt;/p&gt;

&lt;p&gt;Fonts:&lt;br&gt;
&lt;a href="https://timdeschryver.dev/blog/google-maps-as-an-angular-component" rel="noopener noreferrer"&gt;https://timdeschryver.dev/blog/google-maps-as-an-angular-component&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>GUI Simples no Linux Utilizando Node.js e Zenity</title>
      <dc:creator>Fernando Raposo da Camara Silva</dc:creator>
      <pubDate>Tue, 01 Jun 2021 02:12:53 +0000</pubDate>
      <link>https://forem.com/ferfox1981/gui-simples-no-linux-utilizando-node-js-e-zenity-1haf</link>
      <guid>https://forem.com/ferfox1981/gui-simples-no-linux-utilizando-node-js-e-zenity-1haf</guid>
      <description>&lt;p&gt;(Este post é uma tradução deste original &lt;a href="https://dev.to/ferfox1981/simple-gui-on-linux-using-zenity-and-node-js-2kei"&gt;em inglês&lt;/a&gt;)&lt;br&gt;
É impressionante a quantidade de ferramentas "secretas" do Linux que não são tão bem conhecidas até hoje. Outro dia mesmo esbarrei com o Zenity. Ele tem a ver com a geração de notificações através do Terminal do Linux. Ele pode permitir fazer scripts mais amigáveis exibindo caixas de diálogo. Usa-se ele tipicamente em scripts shell para aumentar a usabilidade.&lt;/p&gt;

&lt;p&gt;Meus objetivos serão os seguintes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Usar o Node.js para acessar dados financeiros relacionados a preços de títulos do Tesouro Direto;&lt;/li&gt;
&lt;li&gt;Criar um mecanismo para de forma sistemática checar o preço dos títulos (minuto a minuto, ou hora por hora...);&lt;/li&gt;
&lt;li&gt;Usar o Zenity para exibir uma notificação com o preço corrente do título.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Acessando Informações do Tesouro Direto
&lt;/h3&gt;

&lt;p&gt;As informações do Tesouro Direto podem ser achadas &lt;a href="https://www.tesourodireto.com.br/titulos/precos-e-taxas.htm"&gt;aqui&lt;/a&gt;. Além disso, se apertarmos o F12 e checarmos a aba Network, veremos o seguinte json sendo recebido pelo browser:&lt;br&gt;
&lt;a href="https://www.tesourodireto.com.br/json/br/com/b3/tesourodireto/service/api/treasurybondsinfo.json"&gt;https://www.tesourodireto.com.br/json/br/com/b3/tesourodireto/service/api/treasurybondsinfo.json&lt;/a&gt;&lt;br&gt;
Podemos ver que este JSON contém as informações instantêneas de cotações do Tesouro Direto.&lt;br&gt;
Assim, não há muito mais o que fazer além de usar o Node.js para fazer chamadas GET e capturar este arquivo json como visto abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const axios = require('axios');
const { exec } = require("child_process");
const https = require('https');



const instance = axios.create({
  httpsAgent: new https.Agent({
    rejectUnauthorized: false
  })
});

instance.get('https://www.tesourodireto.com.br/json/br/com/b3/tesourodireto/service/api/treasurybondsinfo.json')
.then(x =&amp;gt; {...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nota: Este &lt;code&gt;rejectUnauthorized: false&lt;/code&gt; tem que ser setado, caso contrário você receberá erro de certificado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agendador de Tarefas
&lt;/h3&gt;

&lt;p&gt;Um cron job é um comando Linux usado para agendar (ou schedular) tarefas a serem executadas em algum momento do futuro. Esta funcionalidade é exatamente o que é necessário para podermos checar as taxas a cada hora. Assim, iremos usar um cron job para chamar o nosso script Node e assim recuperar as taxas do tesouro direto a cada hora.&lt;br&gt;
Para criar um Cron Job vá em:&lt;br&gt;
&lt;code&gt;/var/spool/cron&lt;/code&gt;&lt;br&gt;
E acesse a tabela cron do usuário escrevendo no prompt:&lt;br&gt;
&lt;code&gt;crontab -e&lt;/code&gt;&lt;br&gt;
O README apresenta orientações sobre como agendar comandos usando a crontab adicionando uma expressão seguida pelo comando que se deseja executar periodicamente.&lt;br&gt;
Por exemplo, se você quiser rodar seu programa a cada minuto entre dez da manhã e cinco da tarde todos os dias úteis da semana escreva o seguinte na crontab:&lt;br&gt;
&lt;code&gt;* 10-17 * * 1-5 &amp;lt;comando&amp;gt;&lt;/code&gt;&lt;br&gt;
Para facilitar esta tarefa existe um site chamado &lt;a href="https://crontab.guru/"&gt;crontab.guru&lt;/a&gt; que ajuda a construir a expressão.&lt;br&gt;
Nota: Para agendar o cron para rodar o seu script DE HORA EM HORA, DE SEGUNDA A SEXTA das dez da manhã às cinco da tarde a expressão é: 0 10-17 * * 1-5&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lembre-se de adicionar o caminho completo do Node e do seu script para que o job na cron tab funcione corretamente.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Notificações Usando Zenity
&lt;/h3&gt;

&lt;p&gt;O Zenity é uma ferramenta que permite a geração de notificações através de comandos no terminal. &lt;a href="https://help.gnome.org/users/zenity/stable/notification.html.en"&gt;Notificações&lt;/a&gt; que se parecem com isso:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2_4eM7Nz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rtmt5jalq7ane6su572l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2_4eM7Nz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rtmt5jalq7ane6su572l.png" alt="image" width="509" height="65"&gt;&lt;/a&gt;&lt;br&gt;
Você pode gerá-las escrevendo no Terminal assim:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zenity --notification\&lt;br&gt;
--window-icon="info" \&lt;br&gt;
--text="There are system updates necessary!"&lt;/code&gt;&lt;br&gt;
Há uma boa chance do Zenity já estar instalado na sua máquina (no Ubuntu está). Mas se você não tem, por favor escreva:&lt;br&gt;
&lt;code&gt;sudo apt-get update -y&lt;/code&gt;&lt;br&gt;
depois, escreva:&lt;br&gt;
&lt;code&gt;sudo apt-get install -y zenity&lt;/code&gt;&lt;br&gt;
Para concluir os objetivos nós precisamos que o Node execute comandos Shell de alguma forma. Isto é alcançado utlizando a biblioteca exec como demonstrada abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  exec('zenity --notification --window-icon="info" --text="Taxa Atual TD 2035: IPCA+"' + taxa, (error, stdout, stderr) =&amp;gt; {
    if (error) {
      console.log(`error: ${error.message}`);
      return;
    }
    if (stderr) {
      console.log(`stderr: ${stderr}`);
      return;
    }
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O projeto inteiro no GitHub está &lt;a href="https://github.com/ferfox1981/td-monitor"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fontes:&lt;br&gt;
&lt;a href="https://help.gnome.org/users/zenity/stable/index.html.en"&gt;https://help.gnome.org/users/zenity/stable/index.html.en&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.howtoforge.com/how-to-display-gui-dialogs-in-bash-script-using-zenity/"&gt;https://www.howtoforge.com/how-to-display-gui-dialogs-in-bash-script-using-zenity/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://crontab.guru/"&gt;https://crontab.guru/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>linux</category>
      <category>gui</category>
      <category>cronjob</category>
    </item>
    <item>
      <title>Simple GUI on Linux Using Zenity and Node.js</title>
      <dc:creator>Fernando Raposo da Camara Silva</dc:creator>
      <pubDate>Thu, 27 May 2021 23:42:59 +0000</pubDate>
      <link>https://forem.com/ferfox1981/simple-gui-on-linux-using-zenity-and-node-js-2kei</link>
      <guid>https://forem.com/ferfox1981/simple-gui-on-linux-using-zenity-and-node-js-2kei</guid>
      <description>&lt;p&gt;It is incredible the amount of "secret" features on Linux that are not well known until today.&lt;br&gt;
I came across a tool called Zenity the other day. It is related to sending UI notifications on Linux.&lt;br&gt;
Zenity is an open-source tool for displaying simple GUI in shell scripts. It makes scripts more user-friendly by displaying GTK+ dialogs. It is tipically used on shell scripting to improve its usability.&lt;/p&gt;

&lt;p&gt;My goal is to do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use Node.js to access financial data related to Brazilian Treasury Bonds (Tesouro Direto in Brazil);&lt;/li&gt;
&lt;li&gt;Create a mechanism to sistematically check instant treasury rates;&lt;/li&gt;
&lt;li&gt;Use Zenity to pop-up a notification to user;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Acessing Tesouro Direto Data
&lt;/h3&gt;

&lt;p&gt;Tesouro Direto Rates can be found &lt;a href="https://www.tesourodireto.com.br/titulos/precos-e-taxas.htm" rel="noopener noreferrer"&gt;here&lt;/a&gt;. In addition, if you press F12 and check Network Tab, you'll see that the following json is received by the browser:  &lt;a href="https://www.tesourodireto.com.br/json/br/com/b3/tesourodireto/service/api/treasurybondsinfo.json" rel="noopener noreferrer"&gt;https://www.tesourodireto.com.br/json/br/com/b3/tesourodireto/service/api/treasurybondsinfo.json&lt;/a&gt; &lt;br&gt;
We can see that it contains all the current treasury rates up to date.&lt;br&gt;
So, there's not much to do other than to use Node.js to make GET commands and capture that json file as shown bellow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const axios = require('axios');
const { exec } = require("child_process");
const https = require('https');



const instance = axios.create({
  httpsAgent: new https.Agent({
    rejectUnauthorized: false
  })
});

instance.get('https://www.tesourodireto.com.br/json/br/com/b3/tesourodireto/service/api/treasurybondsinfo.json')
.then(x =&amp;gt; {...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: That &lt;code&gt;rejectUnauthorized: false&lt;/code&gt; is important to be set, otherwise you will get a certificate error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Task Scheduler
&lt;/h3&gt;

&lt;p&gt;A cron job is a Linux command used for scheduling tasks to be executed sometime in the future. This feature is exactly what is needed to check the desired rates every hour. So, we will use a cron job to call our Node script to get the treasury bond rates every hour.&lt;br&gt;
To create your Cron Job go to:&lt;br&gt;
&lt;code&gt;/var/spool/cron&lt;/code&gt;&lt;br&gt;
And access user's cron tab by typing:&lt;br&gt;
&lt;code&gt;crontab -e&lt;/code&gt;&lt;br&gt;
The README presents orientation about how to schedule commands using crontab by adding some expressionfollowed by the command that needs to be executed.&lt;br&gt;
For instance, if you want your program to run every minute from 10AM to 17PM every weekday, write the following:&lt;br&gt;
&lt;code&gt;* 10-17 * * 1-5 &amp;lt;command&amp;gt;&lt;/code&gt;&lt;br&gt;
In order to ease this task, there is a site called &lt;a href="https://crontab.guru/" rel="noopener noreferrer"&gt;crontab.guru&lt;/a&gt; that helps us to construct the expression. &lt;br&gt;
Note: To schedule cron to run your script EVERY HOUR of EVERY WEEKDAY from 10AM to 17PM, the expression is: 0 10-17 * * 1-5 &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remember to add the full path of Node and script to make the cron tab job to work properly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Notifications Using Zenity
&lt;/h2&gt;

&lt;p&gt;Zenity is a tool that enables the generation of dialogs from terminal commands. &lt;a href="https://help.gnome.org/users/zenity/stable/notification.html.en" rel="noopener noreferrer"&gt;Notifications&lt;/a&gt; look like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckjsjqgap60xf32vhglv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckjsjqgap60xf32vhglv.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
 You can generate them by typing on Terminal:&lt;br&gt;
&lt;code&gt;zenity --notification\&lt;br&gt;
    --window-icon="info" \&lt;br&gt;
    --text="There are system updates necessary!"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There's a good chance that Zenity is alredy installed on your machine (In Ubuntu it is). If you do not have it, please type:&lt;br&gt;
&lt;code&gt;sudo apt-get update -y&lt;/code&gt;&lt;br&gt;
next, type:&lt;br&gt;
&lt;code&gt;sudo apt-get install -y zenity&lt;/code&gt;&lt;br&gt;
To conclude our goals we need a way to make Node run shell commands and process their I/O. This is achieved by using exec library as shown bellow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  exec('zenity --notification --window-icon="info" --text="Taxa Atual TD 2035: IPCA+"' + taxa, (error, stdout, stderr) =&amp;gt; {
    if (error) {
      console.log(`error: ${error.message}`);
      return;
    }
    if (stderr) {
      console.log(`stderr: ${stderr}`);
      return;
    }
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entire Github project is available &lt;a href="https://github.com/ferfox1981/td-monitor" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fonts:&lt;br&gt;
&lt;a href="https://help.gnome.org/users/zenity/stable/index.html.en" rel="noopener noreferrer"&gt;https://help.gnome.org/users/zenity/stable/index.html.en&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.howtoforge.com/how-to-display-gui-dialogs-in-bash-script-using-zenity/" rel="noopener noreferrer"&gt;https://www.howtoforge.com/how-to-display-gui-dialogs-in-bash-script-using-zenity/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://crontab.guru/" rel="noopener noreferrer"&gt;https://crontab.guru/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>linux</category>
      <category>gui</category>
      <category>cronjob</category>
    </item>
    <item>
      <title>Tree Ways to Scroll to an Element using Angular</title>
      <dc:creator>Fernando Raposo da Camara Silva</dc:creator>
      <pubDate>Sun, 02 May 2021 02:30:00 +0000</pubDate>
      <link>https://forem.com/ferfox1981/tree-ways-to-scroll-to-an-element-using-angular-1dlj</link>
      <guid>https://forem.com/ferfox1981/tree-ways-to-scroll-to-an-element-using-angular-1dlj</guid>
      <description>&lt;p&gt;Recently I was implementing in Angular a requirement that demanded the following: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"After pressing a button, if some specific data is returned, present a warning with a link saying that the specific data exists. After clicking on that link, scroll down to the grid containing the data".&lt;/em&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, I tried the simplest solution, which was the use of DOM commands like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView"&gt;Element.scrollIntoView()&lt;/a&gt;, or &lt;br&gt;
&lt;code&gt;document.getElementById("&amp;lt;yourTarget&amp;gt;").scrollIntoView({&lt;br&gt;
      behavior: "smooth",&lt;br&gt;
      block: "start",&lt;br&gt;
      inline: "nearest"&lt;br&gt;
    });&lt;/code&gt;&lt;br&gt;
(Remeber to add &lt;code&gt;id="&amp;lt;yourtarget"&lt;/code&gt; where you want to scroll)&lt;br&gt;
It worked on development, and it was quite easy, but after deploying to production environment I noticed that the scroll was &lt;strong&gt;not working!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, I tried another way, using Angular's &lt;a href="https://angular.io/api/common/ViewportScroller"&gt;ViewportScroller&lt;/a&gt;.&lt;br&gt;
In order to do that, you have to inject ViewportScroller at Component's constructor, like &lt;code&gt;constructor(private scroller: ViewportScroller)&lt;/code&gt; and just call &lt;code&gt;this.scroller.scrollToAnchor("&amp;lt;yourTarget&amp;gt;");&lt;/code&gt;. Again, no big deal, and again it was NOT WORKING on production environment.&lt;/p&gt;

&lt;p&gt;The third way to do it, is to use Router to provide navigation to the anchor I wanted. Similarly to the last option, inject Router to constructor, like &lt;code&gt;constructor(private router: Router)&lt;/code&gt;, and use the command:&lt;br&gt;
&lt;code&gt;this.router.navigate([], { fragment: "&amp;lt;yourTarget&amp;gt;" });&lt;/code&gt;&lt;br&gt;
Finally it DID WORK on production environment! I don't know for sure why the previous methods failed, I read some sources that says Angular Material blocks scrolling, but I'm not sure.&lt;br&gt;
In order to present the different options there's a &lt;a href="https://stackblitz.com/edit/scrolling-types?embed=1&amp;amp;file=src/app/app.component.ts"&gt;Stackblitz&lt;/a&gt; as an example.&lt;br&gt;
There you can click on tree buttons, each one using a different method to scroll down to some anchor.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/scrolling-types?embed=1&amp;amp;&amp;amp;" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;br&gt;
Hope it helps someone :)&lt;/p&gt;

</description>
      <category>angular</category>
      <category>html</category>
    </item>
  </channel>
</rss>
