# :a: Apostila Angular - parte 2 ## [Rotas - Router](https://angular.io/guide/router "Ir para o site oficial") ![](https://i.imgur.com/D4g0YZ7.png) O Angular Router é um poderoso roteador JavaScript construído e mantido pela equipe do Angular Core que pode ser instalada a partir do @angular/routerpacote. Ele fornece uma biblioteca de roteamento completa com a possibilidade de ter várias saídas de roteador, diferentes estratégias de correspondência de caminho, fácil acesso aos parâmetros de roteamento e guardas de rota para proteger os componentes contra acesso não autorizado. O roteador Angular é uma parte essencial da plataforma Angular. Ele permite que os desenvolvedores criem aplicativos de página única com várias visualizações e permitam a navegação entre essas visualizações. O Angular Router permite a navegação de uma view para a próxima conforme os usuários executam as tarefas da aplicação. ### Visão geral O navegador é um modelo familiar de navegação de aplicativos: * Digite um URL na barra de endereços e o navegador navega para uma página correspondente. * Clique nos links na página e o navegador navega para uma nova página. * Clique nos botões Voltar e Avançar do navegador e o navegador navega para trás e para frente no histórico de páginas que você viu. O Angular Router("o roteador") empresta esse modelo. Ele pode interpretar uma URL do navegador como uma instrução para navegar para uma visualização gerada pelo cliente. Ele pode passar parâmetros opcionais ao componente de visualização de suporte que o ajudam a decidir qual conteúdo específico apresentar. Você pode vincular o roteador a links em uma página e ele navegará para a visualização do aplicativo apropriada quando o usuário clicar em um link. Você pode navegar imperativamente quando o usuário clica em um botão, seleciona em uma caixa suspensa ou em resposta a algum outro estímulo de qualquer origem. E o roteador registra a atividade no diário de histórico do navegador para que os botões de voltar e avançar também funcionem ### Comando criação de rota manualmente: ```typescript= ng generate module app-routing --flat --module=app ``` Onde: |Comando| Descrição| |---|---| |- -flat | Flag que indica se deve ser criado um diretório no qual os arquivos do componente serão colocados. Valor padrão: true.| |- -module <string> |Define para qual módulo da aplicação este componente deve ser criado.| ### Configuração: Um aplicativo Angular roteado tem uma instância singleton do Routerserviço. Quando o URL do navegador muda, esse roteador procura um correspondente Route do qual possa determinar o componente a ser exibido. Um roteador não tem rotas até você configurá-lo. O exemplo a seguir cria cinco definições de rotas, configura o roteador através do RouterModule.forRoot()método, e adiciona o resultado ao AppModule's importsmatriz. ```typescript= const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'hero/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroListComponent, data: { title: 'Heroes List' }}, { path: '', redirectTo: '/heroes', pathMatch: 'full'}, { path: '**', component: PageNotFoundComponent } ]; ``` A **appRoutes** matriz de rotas descreve como navegar. Passe para o ==RouterModule.forRoot()== método no módulo importspara configurar o roteador. Cada **Route** um mapeia um URL pathpara um componente. Não há barras principais no caminho . O roteador analisa e constrói o URL final para você, permitindo que você use os caminhos relativo e absoluto ao navegar entre os modos de exibição do aplicativo. A **:id** segunda rota é um token para um parâmetro de rota. Em um URL como /hero/42"42" é o valor do idparâmetro. O correspondente HeroDetailComponent usará esse valor para encontrar e apresentar o herói cujo id42 é. Você aprenderá mais sobre os parâmetros de rota mais adiante neste guia. A **data** propriedade na terceira rota é um local para armazenar dados arbitrários associados a essa rota específica. A propriedade de dados é acessível dentro de cada rota ativada. Use-o para armazenar itens como títulos de páginas, texto de trilhas e outros dados estáticossomente leitura . Você usará o protetor de resolução para recuperar dados dinâmicos posteriormente no guia. O **caminho vazio** na quarta rota representa o caminho padrão para o aplicativo, o local a ser percorrido quando o caminho na URL está vazio, como normalmente é no início. Essa rota padrão redireciona para a rota da /heroesURL e, portanto, exibirá a HeroesListComponent. O **caminho na última rota** é um curinga . O roteador selecionará essa rota se a URL solicitada não corresponder a nenhum caminho para as rotas definidas anteriormente na configuração. Isso é útil para exibir uma página "404 - Não encontrado" ou redirecionar para outra rota. A ordem das rotas na configuração é importante e isso é por design. O roteador usa uma estratégia de ganhos de primeira partida ao combinar rotas, portanto rotas mais específicas devem ser colocadas acima de rotas menos específicas. Na configuração acima, as rotas com um caminho estático são listadas primeiro, seguidas por uma rota de caminho vazia, que corresponde à rota padrão. A rota curinga vem por último porque corresponde a cada URL e deve ser selecionada apenas se nenhuma outra rota for correspondida primeiro. Se você precisar ver quais eventos estão ocorrendo durante o ciclo de vida da navegação, há a opção enableTracing como parte da configuração padrão do roteador. Isso produz cada evento de roteador que ocorreu durante cada ciclo de vida de navegação no console do navegador. Isso só deve ser usado para fins de depuração. Você define a enableTracing: trueopção no objeto passado como o segundo argumento para o RouterModule.forRoot()método. ### Router-outlet O Router-Outlet é uma diretiva que está disponível na biblioteca do roteador onde o roteador insere o componente que é correspondido com base na URL do navegador atual. Você pode adicionar várias tomadas em seu aplicativo Angular, o que permite implementar cenários avançados de roteamento. ```angular= <router-outlet></router-outlet> ``` Qualquer componente que seja correspondido pelo roteador o renderizará como um irmão da saída do roteador. ### Rotas e Caminhos Rotas são definições (objetos) compostas de pelo menos um caminho e um componente (ou um redirecionamento para o caminho) atributos. O caminho refere-se à parte da URL que determina uma visualização exclusiva que deve ser exibida, e o componente refere-se ao componente Angular que precisa ser associado a um caminho. Com base em uma definição de rota que fornecemos (por meio de um ==RouterModule.forRoot== (routes)método estático ), o roteador é capaz de navegar pelo usuário para uma visualização específica. Cada Route mapeia um URL pathpara um componente. O caminho pode estar vazio, o que denota o caminho padrão de um aplicativo e geralmente é o início do aplicativo. O caminho pode ter uma sequência curinga ( ** ). O roteador selecionará essa rota se a URL solicitada não corresponder a nenhum caminho para as rotas definidas. Isso pode ser usado para exibir uma exibição "Não encontrado" ou redirecionar para uma exibição específica se nenhuma correspondência for encontrada. Este é um exemplo de uma rota: ```angular= { path: 'contacts', component: ContactListComponent} ``` Se essa definição de rota for fornecida para a configuração do roteador, o roteador renderizará *ContactListComponent* quando a URL do navegador para o aplicativo da web se tornar */contacts*. **Estratégias de correspondência de Rota:** O roteador angular fornece diferentes estratégias de correspondência de rotas. A estratégia padrão é simplesmente verificar se o URL do navegador atual é prefixado com o caminho. Por exemplo, nossa rota anterior ```angular= { path: 'contacts', component: ContactListComponent} ``` Poderia também ser escrito como: ```angular= { path: 'contacts',pathMatch: 'prefix', component: ContactListComponent} ``` O patchMathatributo especifica a estratégia de correspondência. Neste caso, é o prefixo que é o padrão. A segunda estratégia de correspondência está cheia . Quando for especificado para uma rota, o roteador verificará se o caminho é exatamente igual ao caminho do URL do navegador atual: ```angular= { path: 'contacts',pathMatch: 'full', component: ContactListComponent} ``` ### Router Params Criar rotas com parâmetros é um recurso comum em aplicativos da web. Roteador Angular permite acessar parâmetros de diferentes maneiras: :arrow_right: Usando o serviço ActivatedRoute , :arrow_right: Usando o ParamMap observável disponível começando com v4. Você pode criar um parâmetro de rota usando a sintaxe de dois pontos . Este é um exemplo de rota com um parâmetro id : ```angular= { path: 'contacts/:id', component: ContactDetailComponent} ``` ### Router Link As ==RouterLink== diretivas nas tags de âncora dão ao roteador controle sobre esses elementos. Os caminhos de navegação são fixos, então você pode atribuir uma string à routerLink(uma ligação "one-time"). Se o caminho de navegação fosse mais dinâmico, você poderia ter vinculado a uma expressão de modelo que retornou uma matriz de parâmetros de link de rota (a matriz de parâmetros de link). O roteador resolve esse array em um URL completo. ### Guarda de Rotas Um roteador de rotas é um recurso do Roteador Angular que permite aos desenvolvedores executar alguma lógica quando uma rota é solicitada e, com base nessa lógica, permite ou nega o acesso do usuário à rota. É comumente usado para verificar se um usuário está logado e tem autorização antes que ele possa acessar uma página. Você pode adicionar um protetor de rota implementando a ==CanActivateinterface== disponível no ==@angular/routerpacote== e estendendo o canActivate()método que contém a lógica para permitir ou negar o acesso à rota. Por exemplo, a guarda a seguir sempre permitirá o acesso a uma rota: ```angular= class MyGuard implements CanActivate { canActivate() { return true; } } ``` Você pode então proteger uma rota com o guarda usando o canActivateatributo: ```angular= { path: 'contacts/:id, canActivate:[MyGuard], component: ContactDetailComponent} ``` ### Diretiva de Navegação O roteador angular fornece a routerLinkdiretiva para criar links de navegação. Essa diretiva leva o caminho associado ao componente para navegar. Por exemplo: ```angular= <a [routerLink]="'/contacts'">Contacts</a> ``` ### Múltiplas saídas e Rotas auxiliares Roteador Angular suporta múltiplas tomadas no mesmo aplicativo. Um componente tem uma rota principal associada e pode ter rotas auxiliares. Rotas auxiliares permitem que os desenvolvedores naveguem em várias rotas ao mesmo tempo. Para criar uma rota auxiliar, você precisará de uma saída de roteador com nome, na qual o componente associado à rota auxiliar será exibido. ```angular= <router-outlet></router-outlet> <router-outlet name="outlet1"></router-outlet> ``` :point_right: A saída sem nome é a saída primária. :point_right: Todas as tomadas devem ter um nome, exceto a saída principal. Você pode então especificar a tomada onde deseja renderizar seu componente usando o atributo outlet: ```angular= { path: "contacts", component: ContactListComponent, outlet: "outlet1" } ``` ## Comandos de Instalação ### Angular Material ```typescrip= ng add @angular/material ``` >? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink Indigo/Pink [ Preview: https://material.angular.io?theme=indigo-pink ] Deep Purple/Amber [ Preview: https://material.angular.io?theme=deeppurple-amber ] Pink/Blue Grey [ Preview: https://material.angular.io?theme=pink-bluegrey ] Purple/Green [ Preview: https://material.angular.io?theme=purple-green ] >#Set up HammerJS for gesture recognition? (Y/n) = Y >#? Set up browser animations for Angular Material? (Y/n) = Y Vá para app > angular-material.module.ts e adicione o codigo. ```typescript= import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, BrowserAnimationsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } ``` ### Material Design Bootstrap ```typescrip= npm i npm-registry-client ng add angular-bootstrap-md ``` ## [JWT](https://jwt.io/ "Ir para o site oficial") ![](https://i.imgur.com/ihbJhNn.png) :arrow_right: [**NPM JWT**](https://www.npmjs.com/package/jsonwebtoken) O JSON Web Token (JWT) é um padrão aberto ( RFC 7519 ) que define uma maneira compacta e independente de transmitir informações com segurança entre as partes como um objeto JSON. Essas informações podem ser verificadas e confiáveis ​​porque são assinadas digitalmente. Os JWTs podem ser assinados usando um segredo (com o algoritmo HMAC ) ou um par de chaves pública / privada usando RSA ou ECDSA . Embora as JWTs possam ser criptografadas para também fornecer sigilo entre as partes, focaremos nos tokens assinados . Os tokens assinados podem verificar a integridade das reivindicações contidas nele, enquanto os tokens criptografados ocultam essas reivindicações de outras partes. Quando os tokens são assinados usando pares de chaves pública / privada, a assinatura também certifica que apenas a parte que detém a chave privada é a pessoa que a assinou. ### Tecnicamente o que é ? Após o registro quando o usuário faz o pedido de login . 1. O servidor verifica se o usuário é legítimo e responde com um token(JWT) contendo a identidade do usuário. 2. O token em resposta é armazenado localmente no sistema do cliente e o usuário é permitido dentro do aplicativo. 3. Quando o usuário faz alterações em seu perfil, seu perfil [dados + token] é enviado para o servidor. 4. O servidor primeiro verifica se o pedido contém o token (responde com um erro se não for passado). O token é então verificado, uma vez feito, os dados do perfil da carga são verificados e as respectivas alterações são feitas no banco de dados. 5. É o mesmo para todas as outras ações feitas pelo usuário. 6. Quando o usuário “desconecta” o token de identificação é destruído do local. O JWT é um padrão (RFC-7519) de mercado que define como transmitir e armazenar objetos JSON de forma compacta e segura entre diferentes aplicações. Os dados nele contidos podem ser validados a qualquer momento pois o token é assinado digitalmente. ### Quando você deve usar JSON Web Tokens? Aqui estão alguns cenários em que JSON Web Tokens são úteis: * **Autorização:** este é o cenário mais comum para o uso do JWT. Após o login do usuário, cada solicitação subsequente incluirá o JWT, permitindo que o usuário acesse rotas, serviços e recursos permitidos com esse token. O Logon único é um recurso que usa amplamente o JWT atualmente, devido à sua pequena sobrecarga e à capacidade de ser facilmente usado em diferentes domínios. * **Troca de informações:** os JSON Web Tokens são uma boa maneira de transmitir informações com segurança entre as partes. Como as JWTs podem ser assinadas (por exemplo, usando pares de chaves públicas / privadas), você pode ter certeza de que os remetentes são quem eles dizem que são. Além disso, como a assinatura é calculada usando o cabeçalho e a carga, você também pode verificar se o conteúdo não foi violado. ### Seções do JWT Ele é formado por três seções: Header, Payload e Signature. :arrow_right: **Header** O Header é um objeto JSON que define informações sobre o tipo do token (typ), nesse caso JWT, e o algorítmo de criptografia usado em sua assinatura (alg), normalmente HMAC SHA256 ou RSA. ![](https://i.imgur.com/81rf0za.png) :arrow_right: **Payload** O Payload é um objeto JSON com as Claims (informações) da entidade tratada, normalmente o usuário autenticado. Essas claims podem ser de 3 tipos: * **Reserved claims(Reivindicações registradas):** atributos não obrigatórios (mas recomendados) que são usados na validação do token pelos protocolos de segurança das APIs. * **sub (subject)** = Entidade à quem o token pertence, normalmente o ID do usuário; * **iss (issuer)** = Emissor do token; * **exp (expiration)** = Timestamp de quando o token irá expirar; * **iat (issued at)** = Timestamp de quando o token foi criado; * **aud (audience)** = Destinatário do token, representa a aplicação que irá usá-lo. Geralmente os atributos mais utilizados são: sub, iss e exp. * **Public claims(Reivindicações públicas):** atributos que usamos em nossas aplicações. Normalmente armazenamos as informações do usuário autenticado na aplicação. * name * roles * permissions * **Private claims(Reivindicações privadas):** atributos definidos especialmente para compartilhar informações entre aplicações. ![](https://i.imgur.com/4NEN3l7.png) > Observe que, para tokens assinados, essas informações, embora protegidas contra adulteração, são legíveis por qualquer pessoa. Não coloque informações secretas na carga útil ou nos elementos de cabeçalho de um JWT, a menos que estejam criptografados. :arrow_right: **Signature** A assinatura é a concatenação dos hashes gerados a partir do Header e Payload usando base64UrlEncode, com uma chave secreta ou certificado RSA. ![](https://i.imgur.com/dZShTtw.png) Essa assinatura é utilizada para garantir a integridade do token, no caso, se ele foi modificado e se realmente foi gerado por você. Isso previne ataques do tipo man-in-the-middle, onde o invasor poderia interceptar a requisição e modificar seu conteúdo, desta forma personificando o usuário com informações falsas. Caso o payload seja alterado, o hash final não será válido pois não foi assinado com sua chave secreta. Apenas quem está de posse da chave pode criar, alterar e validar o token. ### Juntando tudo A saída são três seqüências de caracteres **Base64-URL** separadas por pontos que podem ser passadas facilmente nos ambientes HTML e HTTP, além de serem mais compactas quando comparadas aos padrões baseados em XML, como SAML. A seguir, é mostrado um JWT com o cabeçalho e a carga útil anteriores codificados e assinado com um segredo. ![](https://i.imgur.com/qDZB6A5.png) --- ### Usando o token Ao fazer login em um serviço de autenticação um token JWT é criado e retornado para o client. Esse token deve ser enviado para as APIs através do header Authorization de cada requisição HTTP com a flag Bearer, conforme ilustra o diagrama abaixo. ==Authorization: Bearer token== ![](https://i.imgur.com/eXjeiIf.png) #### Diagrama de sequência usando token JWT Em posse do token, a API não precisa ir até o banco de dados consultar as informações do usuário, pois contido no próprio token JWT já temos suas credenciais de acesso. **JWT**, resumidamente, é uma string de caracteres codificados que, caso cliente e servidor estejam sob HTTPS, permite que somente o servidor que conhece o ‘segredo’ possa ler o conteúdo do token, e assim confirmar a autenticidade do cliente. Ou seja, quando um usuário se autentica no sistema (com usuário e senha), o servidor gera um token com data de expiração pra ele. Durante as requisições seguintes do cliente, o JWT é enviado no cabeçalho da requisição e, caso esteja válido, a API irá permitir acesso aos recursos solicitados, sem a necessidade de se autenticar novamente. ![](https://i.imgur.com/jPw2OTV.png) O conteúdo do JWT é um payload JSON que pode conter a informação que você desejar, que lhe permita mais tarde conceder autorização a determinados recursos para determinados usuários. Minimamente ele terá o ID do usuário autenticado, mas pode conter muito mais do que isso. saiba a diferença, autenticação é você provar que você é você mesmo. Já autorização, é você provar que possui permissão para fazer ou ver o que você está tentando. Antes de emitir o JWT, é necessário que o usuário passe por uma autenticação tradicional, geralmente com usuário e senha. Essa informação fornecida é validada junto a uma base de dados e somente caso ela esteja ok é que geramos o JWT para ele. ![](https://i.imgur.com/se1IrAo.png) ## [Material Design Bootstrap](https://mdbootstrap.com/) ![](https://i.imgur.com/fbc6gzZ.png) O Material Design for Bootstrap é um kit de ferramentas de código aberto baseado no Bootstrap para desenvolver aplicativos de Material Design com HTML, CSS e JS. Crie rapidamente protótipos de suas ideias ou construa seu aplicativo inteiro com nossas variáveis e mixins Sass, sistema de grade responsivo, extensos componentes pré-construídos e poderosos plugins construídos em jQuery. ![](https://i.imgur.com/XbiI2g0.png) Desenvolvido em 2014 pelo Google, o Material Design é uma “linguagem de design” . Ele é baseado nos motivos de "cartão" que foram introduzidos pela primeira vez no Google Now e expandiu isso, incluindo transições e animações responsivas, efeitos como iluminação e sombras e layouts baseados em grade. Sendo uma linguagem de design, o Material Design define um conjunto de diretrizes que mostram como melhor projetar um website. Ele informa quais botões são para uso e quais você deve usar, como animar ou movê-lo, bem como onde e como ele deve ser colocado, etc. É uma linguagem de design para dispositivos móveis , que pode ser usada em todas as versões compatíveis do Android, proporcionando uma experiência consistente e de qualidade em todos os aplicativos e plataformas Android, que também podem ser expandidos para outras plataformas e aplicativos, principalmente por meio de APIs para desenvolvedores de terceiros. Além da facilidade de implementação e uso, outro grande recurso dessa plataforma de design é a falta de dependência de estruturas e bibliotecas JavaScript . Em vez disso, ele se baseia em uma estrutura de design de materiais que facilita a utilização e fornece modelos personalizáveis e proporcionam muita liberdade criativa, ajudando a criar sites que se destacam. ### Comandos para instalar ```typescript= npm i npm-registry-client ng add angular-bootstrap-md ``` ## Angular Material ![](https://i.imgur.com/BFMzr6o.png) O Angular Material é um pacote de terceiros usado em projetos Angular para facilitar o processo de desenvolvimento através da reutilização de componentes comuns, como cartões, belas entradas, tabelas de dados e assim por diante. A lista de componentes disponíveis é grande e continua a crescer enquanto falamos. Portanto, para obter uma referência completa dos componentes com exemplos, consulte o site oficial . Com o Angular, o aplicativo inteiro é uma composição de componentes e, em vez de criar e modelar componentes do grupo, você pode aproveitar o Material Angular, que fornece componentes estilizados prontos para uso que seguem as Especificações de design do material . Essa especificação é usada pelo Google no sistema operacional Android e também é muito popular na Web devido a seus belos utilitários de interface do usuário. ### Instalações #### Material Angular ```typescript= ng add @angular/material ``` #### Flexbox ```typescript= npm install @angular/flex-layout@v5.0.0-beta.14 rxjs-compat ``` No app.module.ts ```typescript= import {FlexLayoutModule} from '@angular/flex-layout'; @NgModule({ imports: [ FlexLayoutModule, ], }) export class AppModule {} ``` ## [Animate css](https://animate.style/") ![](https://i.imgur.com/0iP5cu9.png) O Animate é o grande astro por trás de toda a magia que vocês estão prestes a testemunhar neste artigo. O Animate.css é um projeto idealizado por Daniel Eden — atualmente designer de produto no Facebook. Como diz em sua descrição no GitHub, o projeto é uma série de animações legais, leves e divertidas para você usar nos seus projetos. Na sua página oficial, temos uma demo de todas as animações que podemos colocar nos nossos elementos. São mais de 30 animações muito bem feitas. ## [Wow js](https://wowjs.uk/ "Ir para o site oficial") ![](https://i.imgur.com/9RuklRQ.png) Essa biblioteca javascript nos auxilia a criar animações que acontecem de acordo com o scroll do usuário no nosso site. Ela se casa muito bem com o animate.css e nos permite configurar uma série de atributos. ## [Jarallax](http://www.jarallax.com/) ![](https://i.imgur.com/QKV5RuN.png) **Jarallax** é uma biblioteca javascript de código aberto que facilita o ajuste do css baseado na interação. Com **Jarallax** é fácil criar um site de rolagem paralaxe. ## [Fontawesome](https://fontawesome.com/ "Ir para o site oficial") ![](https://i.imgur.com/WGE7tld.png) **Font Awesome** é um conjunto de ferramentas de fontes e ícones com base em CSS e LESS. Foi feito por Dave Gandy para uso com o Twitter Bootstrap e mais tarde foi incorporado no BootstrapCDN. Font Awesome tem uma participação de mercado de 20% entre os sites que usam Font Scripts de terceiros em sua plataforma, classificando o segundo lugar após o Google Fonts, O Font Awesome é uma biblioteca de ícones e ferramentas baseada em CSS e fontes. Ela oferece uma ampla variedade de ícones vetoriais que podem ser facilmente utilizados em projetos web e de design. Aqui estão alguns pontos-chave sobre o Font Awesome: 1. **Ícones Vetoriais:** Ao contrário das imagens tradicionais, os ícones do Font Awesome são vetoriais, o que significa que podem ser dimensionados sem perder qualidade ou nitidez. Isso é especialmente útil em projetos responsivos, onde os elementos precisam se adaptar a diferentes tamanhos de tela. 2. **Fácil Implementação:** O Font Awesome pode ser facilmente implementado em projetos web através de várias formas, como CDN (Content Delivery Network), download local dos arquivos ou integração com ferramentas de desenvolvimento como o npm. 3. **Personalização:** A biblioteca oferece opções de personalização dos ícones, como tamanho, cor, sombra, entre outros, utilizando classes CSS específicas. 4. **Variedade de Ícones:** O Font Awesome possui uma vasta coleção de ícones para diversas categorias, como tecnologia, negócios, mídia social, interface do usuário, entre outros. Isso permite aos desenvolvedores e designers encontrar facilmente os ícones adequados para seus projetos. 5. **Compatibilidade:** Os ícones do Font Awesome são compatíveis com a maioria dos navegadores modernos, garantindo uma experiência consistente para os usuários. 6. **Facilidade de Uso:** A integração dos ícones é simples, exigindo apenas a inclusão das classes CSS apropriadas nos elementos HTML onde os ícones devem ser exibidos. O Font Awesome é uma ferramenta valiosa para adicionar ícones de alta qualidade e escaláveis em projetos web, proporcionando uma experiência visual atraente e funcional aos usuários. . . . ## LocalStorage ![](https://i.imgur.com/VSujYO1.png) **LocalStorage** e **SessionStorage**, parte da API de armazenamento da web, são duas ótimas ferramentas para salvar pares chave / valor localmente. Se você clicar no botão Salvar na parte superior desta postagem, o localStorage é o que é usado para armazenar suas postagens salvas. Tanto o **localStorage** quanto o **sessionStorage** oferecem vantagens em comparação ao uso de cookies: * Os dados são salvos apenas localmente e não podem ser lidos pelo servidor, o que elimina o problema de segurança que os cookies apresentam. * Ele permite que muito mais dados sejam salvos ( 10Mb para a maioria dos navegadores). * É mais simples de usar e a sintaxe é muito simples. * Também é suportado em todos os navegadores modernos, para que você possa usá-lo hoje sem problemas. Obviamente, como os dados não podem ser lidos no servidor, os cookies ainda têm um uso, especialmente quando se trata de autenticação. ### LocalStorage vs SessionStorage **localStorage** e **sessionStorage** realizam exatamente a mesma coisa e têm a mesma API, mas com **sessionStorage** os dados são mantidos até que a janela ou a guia seja fechada, enquanto com **localStorage** os dados persistem até que o usuário limpe manualmente o cache do navegador ou até o aplicativo da web limpa os dados. Os exemplos nesta postagem são para localStorage, mas a mesma sintaxe funciona para **sessionStorage**. ### Usando o localStorage O **localStorage** salva dados no computador do visitante, que ficam vinculados ao (e apenas acessíveis pelo) seu domínio. E pra usar é bem simples: Use o método setItem(nome, valor) para criar/salvar novos itens e o depois o método getItem(nome) para recuperar o valor. ```typescript= // Cria um item "usuario" com valor "Belem" window.localStorage.setItem('usuario', 'Belem'); // Depois, em outra página ou aba, recupera esse item var usuario = window.localStorage.getItem('usuario'); // Remove o item window.localStorage.removeItem('usuario'); ``` ### Usando o sessionStorage Já o sessionStorage faz exatamente a mesma coisa, só que os dados ficam salvos apenas durante a sessão (e são apagados quando o visitante fecha a aba/navegador): ## Diretivas ![](https://i.imgur.com/Q4C8Eoh.jpg) Como seu elemento DOM (Modelo de Objeto de Documento) se comporta de uma certa maneira, sim, você pode fazer isso em Angular. Podemos anexar um comportamento especificado a um elemento DOM em nosso aplicativo angular. Isso é feito com a ajuda de um decorador **@Directive**. As **diretivas** são como um marcador em nossos elementos DOM, que as fazem se comportar de uma maneira especificada. Existem muitas diretivas embutidas no Angular em diferentes categorias que discutiremos daqui a pouco. ### Para que usamos diretivas? As diretivas são usadas principalmente quando queremos um Componente HTML reutilizável, um comportamento HTML reutilizável ou sempre que interagimos com o DOM. A convenção de nomenclatura seguida pelas **diretivas** é ng seguida pelo objetivo da diretiva . No entanto, quando criamos nossas próprias diretivas personalizadas, podemos usar qualquer convenção de acordo com nossa conveniência. Algumas das diretivas mais usadas no Angular são: * ng-bind, * ng-model, * ng-hide, * ng-init etc. Falando sobre os diferentes tipos de diretivas no Angular, existem três tipos de diretivas. * Componente * Diretivas de Atributos * Diretivas de estrutura ![](https://i.imgur.com/v3min8m.png) ### Componentes **Componentes** são as diretivas mais usadas no Angular que, quando usadas como decorador acima da classe, fazem com que ele se comporte de acordo com o comportamento especificado na definição de diretiva. Estes também são conhecidos como auto-contido directivas. Os **componentes** têm seu próprio HTML conhecido como modelo. Um exemplo de um componente está listado abaixo: ```typescript= @Component ({ seletor: 'app-root', template: `<h1> Olá, eu sou um exemplo de COmponents </h1>` }) classe de exportação AppComponent { } ``` ### Diretivas estruturais **Diretivas estruturais** são as diretivas usadas para modificar o layout adicionando ou removendo os elementos DOM. São como diretivas condicionais. As **diretivas estruturais** mais usadas são * ngIf e * ngFor . Vamos primeiro ver como * ngIf funciona. ```typescript= @Componente({ seletor: 'app-root', template: `<h2> Bem-vindo </h2> <p * ngIf = "show"> Mostrar </p> ` }) classe de exportação Component { show público = verdadeiro; } ``` No código acima, se o valor de show for verdadeiro, ele exibirá Show no navegador, senão nada; assim como uma declaração if. Da mesma forma, uma diretiva * ngFor funciona como um loop for. Vamos ver o código na lista abaixo: ```typescript= @Componente({ seletor: 'app-root', template: `<h2> Bem-vindo </h2> <p * ngIf = "show"> Mostrar </p> <ul> <li * ngFor = "deixe o item dos itens"> {{item}} </li> </ul> ` }) classe de exportação Component { show público = verdadeiro; item público = 'lápis'; itens públicos = ['borracha', 'apontador', 'caneta', 'lápis', 'geometria']; } ``` Existem muitas outras diretivas de estrutura como ngSwitch, ngSwitchWhen etc. ### Diretivas de Atributos Agora, quando queremos alterar o atributo, como o nome sugere, a cor, o estilo da fonte, a cor do plano de fundo e a função de uma propriedade, usamos diretivas de atributo nesse caso. Agora, suponha que eu tenha algum texto no meu navegador e desejo alterar a cor e o tamanho da fonte desse texto. Para fazer isso, eu precisaria usar a diretiva de atributo. Uma coisa mais importante a saber aqui é que também podemos criar nossas próprias diretivas de atributos personalizados e aplicar nossos próprios comportamentos especificados aos objetos, mas abordaremos isso mais tarde. Vamos ver um exemplo de diretivas de atributo: ```typescript= @Componente({ seletor: 'app-root', template: `<h2> Bem-vindo </h2> <p [ngStyle] = "{'estilo da fonte': estilo, 'tamanho da fonte': tamanho}"> Meu texto </p> ` }) classe de exportação Component { // show público = true; estilo público = 'itálico'; tamanho público = '30px'; } ``` ## TypeOrm ![](https://i.imgur.com/GTpcWVn.png) O TypeORM é um ORM que pode ser executado nas plataformas NodeJS, Navegador, Cordova, PhoneGap, Ionic, React Native, NativeScript, Expo e Electron e pode ser usado com TypeScript e JavaScript (ES5, ES6, ES7, ES8). Seu objetivo é sempre oferecer suporte aos recursos mais recentes do JavaScript e fornecer recursos adicionais que o ajudem a desenvolver qualquer tipo de aplicativo que use bancos de dados - desde aplicativos pequenos com algumas tabelas a aplicativos corporativos em larga escala com vários bancos de dados. O TypeORM suporta os padrões Active Record e Data Mapper , diferentemente de todos os outros ORMs JavaScript existentes no momento, o que significa que você pode escrever aplicativos de alta qualidade, de baixo acoplamento, escalabilidade e manutenção da maneira mais produtiva. O TypeORM é altamente influenciado por outros ORMs, como Hibernate , Doctrine e Entity Framework ### Para criar um projeto TypeOrm ```typescript= typeorm init --name myproject --database mysql ``` ### Comandos para instalação ```typescript= npm install -g typeorm //instalação global (na maquina) npm install -g ts-node //instalação global (na maquina) npm install typeorm --save //instalação no projeto npm install reflect-metadata --save //instalação no projeto npm install @types/node --save //instalação no projeto ``` Alguns recursos do TypeORM: * suporta DataMapper e ActiveRecord (sua escolha) * entidades e colunas * tipos de coluna específicos do banco de dados * gerente de entidade * repositórios e repositórios personalizados * modelo relacional de objeto limpo * associações (relações) * relações ansiosas e preguiçosas * relações unidirecionais, bidirecionais e auto-referenciadas * suporta vários padrões de herança * cascatas * índices * transações * migrações e geração automática de migrações * pool de conexão * replicação * usando várias conexões com o banco de dados * trabalhando com vários tipos de bancos de dados * consultas entre bancos de dados e esquemas cruzados * sintaxe elegante, flexível e poderoso QueryBuilder * junções esquerda e interna * paginação adequada para consultas usando junções * cache de consulta * streaming de resultados brutos * exploração madeireira * ouvintes e assinantes (ganchos) * suporta padrão de tabela de fechamento * declaração de esquema em modelos ou arquivos de configuração separados * configuração de conexão nos formatos json / xml / yml / env * suporta MySQL / MariaDB / Postgres / CockroachDB / SQLite / Microsoft SQL Server / Oracle / sql.js * suporta banco de dados MongoDB NoSQL * trabalha nas plataformas NodeJS / Navegador / Ionic / Cordova / React Native / NativeScript / Expo / Electron * Suporte TypeScript e JavaScript * O código produzido é de alto desempenho, flexível, limpo e sustentável * segue todas as melhores práticas possíveis * CLI ### Instalação Instale o pacote npm: ```javascript= npm install typeorm --save ``` Você precisa instalar o reflect-metadatashim: ```javascript= npm install reflect-metadata --save ``` e importe-o em algum lugar no local global do seu aplicativo (por exemplo, em app.ts): ```javascript= import "reflect-metadata"; ``` Pode ser necessário instalar as tipagens dos nós: ```javascript= npm install @types/node --save ``` #### Instale um driver de banco de dados: para MySQL ou MariaDB ```javascript= npm install mysql --save(você também pode instalar mysql2) ``` para PostgreSQL ou CockroachDB ```javascript= npm install pg --save ``` para SQLite ```javascript= npm install sqlite3 --save ``` para Microsoft SQL Server ```javascript= npm install mssql --save ``` para sql.js ```javascript= npm install sql.js --save ``` para Oracle ```javascript= npm install oracledb --save ``` Instale apenas um deles, dependendo do banco de dados que você usa. Para fazer o trabalho driver Oracle, você precisa seguir as instruções de instalação do seu site. para MongoDB (experimental) ```javascript= npm install mongodb --save ``` ## NestJS :link: **`https://nestjs.com/`** ![](https://i.imgur.com/2Xl5uMI.jpg) Documentação: https://docs.nestjs.com/ :point_left: ![](https://i.imgur.com/dCiY1Vh.png) O **Nest** é uma estrutura para criar aplicativos eficientes e escalonáveis do lado do servidor Node.js. Ele usa JavaScript moderno, é construído com TypeScript (preserva a compatibilidade com JavaScript puro) e combina elementos de OOP (Programação Orientada a Objetos), FP (Programação Funcional) e FRP (Programação Reativa Funcional). Sob o capô, o **Nest** faz uso do **Express** , mas também oferece compatibilidade com uma grande variedade de outras bibliotecas, como, por exemplo , o Fastify , permitindo o fácil uso dos inúmeros plugins de terceiros disponíveis. Nos últimos anos, graças ao Node.js., o JavaScript se tornou a "língua franca" da Web para aplicativos front-end e back-end, dando origem a projetos incríveis como Angular , React e Vue, que melhoram a produtividade do desenvolvedor e permitem a construção rápida, aplicativos frontend testáveis ​​e extensíveis. No entanto, no lado do servidor, embora existam muitas excelentes bibliotecas, auxiliares e ferramentas para o Node, nenhum deles resolve efetivamente o principal problema - a arquitetura. O objetivo da Nest é fornecer uma arquitetura de aplicativos pronta para uso, que permita a criação sem esforço de aplicativos altamente testáveis, escaláveis, com acoplamento fraco e de fácil manutenção. ### Criar um projeto, instalar e rodar ```javascript= npm i -g @nestjs/cli //instalar a biblioteca nest new project-name //criar o projeto npm i --save @nestjs/core @nestjs/common rxjs reflect-metadata npm install //instalar o package npm run start //iniciar o projeto ``` ### Passport O **Passport**.js é um dos middlewares de autenticação mais antigos, conhecidos pelo desenvolvimento do Node.js. Ele fornece um alto nível de flexibilidade em termos de escolha de qual estratégia de autenticação usar para autenticar seus usuários. O **Nest.js** oferece a biblioteca de autenticação @ nestjs / passport que agrupa a funcionalidade do Passport.js e se integra perfeitamente ao sistema de Injeção de Dependência do Nest.js. O **Passport.js** geralmente é usado e configurado como um Node Middleware. No entanto, no Nest.js, a biblioteca @ nestjs / passport fornece o AuthGuard. Isso é usado para sugerir que a autenticação do Passport é necessária em um Controlador ou Ação específica no Controlador. #### Instalação: ```javascript= npm i @nestjs/passport passport passport-local passport-jwt bcryptjs ``` Definições de TypeScript correspondentes para os seguintes pacotes executando este comando: ```javascript= @types/passport @types/bcryptjs -D ``` ### Modules ![](https://i.imgur.com/EoGyulu.png) Módulos no Nest.js é a forma básica de construir e agrupar blocos de código de maneira coesa. Para iniciar o Nest.js, nós precisamos informar o módulo raiz da nossa aplicação, logo, a boa prática diz que você deve organizar sua aplicação em um formato de arvore, com um módulo raiz e os seguintes serão suas funcionalidades. ![](https://i.imgur.com/Y0VSEb9.png) Para informar ao Nest.js qual será o nosso módulo raiz, precisamos utilizar a classe NestFactory para criar, não apenas a raiz mas toda a arvore de módulos. ![](https://i.imgur.com/1RImUgM.png) ### Controllers Como em muitas outras plataformas, Java/Spring ou C#/ASP.NET, controllers no Nest.js são resposaveis por auxiliar no trabalho de receber e tratar uma requisição HTTP, para definir um novo controller, é necessário: * Expor uma classe nova * Utilizar o decorator @Controller() * Adicionar a classe em um módulo, mesmo que seja no raiz * Decorar algum método com @Get() ou @Post() para receber um requisição get ou post * ![](https://i.imgur.com/Ekezuxu.png) ### Providers ![](https://i.imgur.com/27jDL1K.png) Quase tudo pode ser considerado como um provedor – provider – service, repository, factory, helper e assim por diante. Todos eles podem injetar dependências através de construtor (Dependency Injection), ou seja, eles podem criar vários relacionamentos entre si. Mas, na verdade, um provedor nada mais é do que apenas uma classe simples anotada com um decorator @Injectable(). ### Components ![](https://i.imgur.com/NsGOs3E.png) Você pode criar componentes que podem ser injetados, utilizando injeção de dependências, em outros componentes. Usualmente você irá utilizar um Service para programar sua lógica de negócios, e um Repository para programar uma interação com uma forma de persistência de dados, como o banco de dados por exemplo. Como exemplo, digamos que temos um Service, que finaliza a compra de um carrinho de compras, para isto, o Servicê irá interagir com um Repository verificando se há os itens em estoque. ![](https://i.imgur.com/YBCFBaH.png) * **tsconfig.json** arquivo para configurar o TypeScript * **nodemon.json** arquivo para configuração do nodemon * **tslint.json** arquivo para aprender TypeScript * **nest-cli.json** para configuração da CLI * **src/pasta** contendo o código real do projeto * **test/pasta** contendo os testes. ### Middlewares ![](https://i.imgur.com/ooovRa0.png) Quando queremos agir, antes dos Controllers, nós podemos criar um Middleware implementando a interface NestMiddleware que deve ser decorada com @Middleware(). Esta interface espera que implementemos o método resolve e que retorne um Express Middleware: (req, res, next) => void. ![](https://i.imgur.com/2T9Zxio.png) ### Exception Filters Temos a nossa disposição uma camada responsável por capturar exceções não tratadas. Nesta camada podemos definir filtros de exceçoes. Para isto, precisamos: * Criar uma classe que implemente ExceptionFilter * Decorar a classe com @Catch() * Implementar o método catch(exception: HttpException, reponse) ## Jasmine :link: **`https://jasmine.github.io/`** ![](https://i.imgur.com/SaoD34E.png) ### Exception filters ![](https://i.imgur.com/KywQAiz.png) A camada de exceções interna é responsável por manipular todas as exceções lançadas em todo o seu aplicativo. Quando uma exceção não tratada é detectada, o usuário final receberá uma resposta adequada. ### Pipes ![](https://i.imgur.com/ZL3WHLi.png) Um pipe é uma classe anotada com o decorator @Injectable(). O pipe deve implementar a interface PipeTransform. ### Guards ![](https://i.imgur.com/d95zpt8.png) Um guarda é uma classe anotada com o decorator @Injectable(). O guarda deve implementar a interface do CanActivate. ### Interceptors ![](https://i.imgur.com/NeriIXZ.png) Um interceptor é uma classe anotada com o decorator @Injectable(). O interceptor deve implementar a interface NestInterceptor. **Jasmine** é uma estrutura de desenvolvimento orientada a comportamento para testar o código **JavaScript**. Não depende de nenhuma outra estrutura JavaScript. Não requer um DOM. E possui uma sintaxe limpa e óbvia, para que você possa escrever facilmente testes. Este guia está sendo executado no **Jasmine versão 2.0.0.** ### Especificações: As especificações são definidas chamando a função **Jasmine** global **`it`**, que, como describe leva uma string e uma função. A sequência é o título da especificação e a função é a especificação ou teste. Uma especificação contém uma ou mais expectativas que testam o estado do código. Uma expectativa no **Jasmine** é uma afirmação que é verdadeira ou falsa. Uma especificação com todas as expectativas verdadeiras é uma especificação de aprovação. Uma especificação com uma ou mais expectativas falsas é uma especificação com falha. #### São apenas funções: Como os blocos describe **`it`** são funções, eles podem conter qualquer código executável necessário para implementar o teste. As regras de escopo do **JavaScript** se aplicam, portanto, as variáveis declaradas em describe estão disponíveis para qualquer **`it`** bloco dentro do conjunto. ### Expectativas: As expectativas são construídas com a função **`expect`** que recebe um valor, chamado de real. É encadeado com uma função **Matcher**, que aceita o valor esperado. ### Matchers: Cada correspondente implementa uma comparação booleana entre o valor real e o valor esperado. É responsável por relatar ao **Jasmine** se a expectativa é verdadeira ou falsa. **Jasmine** passará ou falhará nas especificações. Qualquer correspondente pode avaliar uma afirmação negativa encadeando a chamada expect com a nota ntes de chamar o correspondente. #### Matchers Incluídos **Jasmine** tem um rico conjunto de matchers incluídos. Cada um é usado aqui - todas as expectativas e especificações passam. Também é possível escrever correspondências personalizadas para quando o domínio de um projeto solicitar asserções específicas que não estão incluídas abaixo. :arrow_right: **toEqual** Esse talvez seja o mais básico e um dos que mais iremos usar. Simplesmente verifica se duas coisas são iguais (e não necessariamente o mesmo objeto). ```javascript= expect(true).toEqual(true); expect([1, 2, 3]).toEqual([1, 2, 3]); ``` :arrow_right: **toBe** O matcher **toBe**, a princípio, parece ser igual ao **toEqual**. A diferença é que **toBe** verifica não só se os dois valores são iguais, mas também se eles são do mesmo objeto. ```javascript= var bob = { model: "Camaro" }; var john = { model: "Camaro" }; expect(bob).toEqual(john); // passa => são equivalentes expect(bob).toBe(john); // falha => não é o mesmo objeto ``` Apesar de bob e john serem similares, eles não são o mesmo objeto, o que faz a spec passar se for usado o matcher toEqual, mas falha se for usado o matcher toBe. O mesmo acontece para arrays: ```javascript= var group = [100, 101, 102]; expect(group).toEqual([100, 101, 102]); // passa => são equivalentes expect(group).toBe([100, 101, 102]); // falha => não é o mesmo array ``` :arrow_right: **toBeTruthy** e **toBeFalsy** Para testar se algum valor é avaliado como true ou false, podemos usar respectivamente os matchers **toBeTruthy** e **toBeFalsy**: ```javascript= expect(true).toBeTruthy(); expect(1000).toBeTruthy(); expect({}).toBeTruthy(); expect("").toBeFalsy(); expect(null).toBeFalsy(); expect(false).toBeFalsy(); ``` Se pararmos pra olhar com calma o exemplo anterior, podemos notar que a avaliação dos matchers **toBeTruthy** e **toBeFalsy** é idêntica ao JavaScript. Então, temos alguns valores específicos que são considerados **falsy** e todo o restante é avaliado como **truthy**. :arrow_right: **not** Muitas vezes podemos inverter um matcher para termos certeza de que ele não é um valor true. Podemos fazer isso facilmente adicionando o prefixo **.not**: ```javascript= expect('Beléim').not.toEqual('Belem'); ``` :arrow_right: **toContain** Conseguimos também verificar se um elemento está contido em um array ou string por exemplo, como o matcher **toContain**. ```javascript= expect([10, 11, 12, 13, 14, 15]).toContain(13); expect('Edson Belem').toContain('Belem'); ``` :arrow_right: **toBeDefined** e **toBeUndefined** Da mesma maneira que vimos os matchers **toBeTruthy** e **toBeFalsy**, Jasmine também nos oferece os **toBeDefined** e **toBeUndefined** que verificam se um valor é defined ou undefined. ```javascript= var iAmUndefined; expect(null).toBeDefined(); // passa expect('Belem').toBeDefined(); // passa expect(iAmUndefined).toBeDefined(); // falha expect(iAmUndefined).toBeUndefined(); // passa expect(12).toBeUndefined(); // falha expect(null).toBeUndefined(); // falha ``` :arrow_right: **toBeNull** Direto ao ponto, esse matcher simplesmente avalia se um valor é **null**: ```javascript= expect(null).toBeNull(); // passa expect(false).toBeNull(); // falha expect(1).toBeNull(); // falha ``` :arrow_right: **toBeNaN** Sem muitas delongas, esse matcher verifica se um valor é **NaN**: ```javascript= expect(0).toBeNaN(); // falha expect(10).not.toBeNaN(); // passa ``` :arrow_right: **toBeGreatherThan** e **toBeLessThan** Esses dois matchers verificam se um valor é **maior** ou **menor** que um outro valor passado. ```javascript= expect(10).toBeGreatherThan(1); // passa expect(10).toBeLessThan(20); // passa ``` :arrow_right: **toBeCloseTo** Esse matcher permite que possamos verificar se um certo número está próximo de um outro número, dado uma certa precisão decimal como segundo argumento. Poderíamos por exemplo, verificar se um número é próximo de 25.23 com um ponto decimal. Poderíamos fazer algo assim: ```javascript= expect(25.23).toBeCloseTo(25.2, 1); // passa ``` :arrow_right: **toMatch** Esse cara verifica se algum valor está de acordo com base em uma expressão regular. ```javascript= expect('Yes, we can!').toMatch(/we/); // passa ``` :arrow_right: **toThrow** Esse matcher permite que verifiquemos se uma função lançou um erro. Como exemplo, vamos imaginar que temos uma função **onlyNumbers** que deve lançar uma exceção caso o argumento passado seja uma string e não um número. Podemos usar aqui uma função anônima para nos facilitar a vida: ```javascript= expect(function() { onlyNumbers('argumento errado') }).toThrow(); ``` ## :warning: Para iniciar o teste :pencil2: Digitar no terminal: ```typescript= ng test ``` :pencil2: O comando **`ng test`** cria o aplicativo no modo de exibição e inicia o **teste de Karma**. Aguardar abrir o projeto no browser. Aparecerá os testes que foram feitos e os que estão comentados (pendentes) ![](https://i.imgur.com/LEIv9Oh.png) --- A saída do **console** se parece um pouco com isso: :::info 10% building modules 1/1 modules 0 active ...INFO [karma]: Karma v1.7.1 server started at http://0.0.0.0:9876/ ...INFO [launcher]: Launching browser Chrome ... ...INFO [launcher]: Starting browser Chrome ...INFO [Chrome ...]: Connected on socket ... Chrome ...: Executed 3 of 3 SUCCESS (0.135 secs / 0.205 secs) ::: A última linha do log é a mais importante. Isso mostra que o **Karma** realizou três testes que foram aprovados. --- ## Formulario Reativo https://angular.io/guide/reactive-forms ![](https://i.imgur.com/MqjchFB.png) Manipular a entrada do usuário com formulários é a pedra angular de muitos aplicativos comuns. Os aplicativos usam formulários para permitir que os usuários efetuem login, atualizem um perfil, insiram informações confidenciais e executem muitas outras tarefas de entrada de dados. Angular fornece duas abordagens diferentes para lidar com a entrada do usuário por meio de formulários: reativo e orientado a modelo. Ambos capturam eventos de entrada do usuário a partir da visualização, validam a entrada do usuário, criam um modelo de formulário e modelo de dados para atualizar e fornecem uma maneira de rastrear alterações. Os formulários reativos fornecem uma abordagem orientada a modelo para lidar com entradas de formulário cujos valores mudam ao longo do tempo. Este guia mostra como criar e atualizar um controle básico de formulário, avançar para o uso de vários controles em um grupo, validar valores de formulário e criar formulários dinâmicos nos quais você pode adicionar ou remover controles em tempo de execução. ### Visão geral Os formulários reativos usam uma abordagem explícita e imutável para gerenciar o estado de um formulário em um determinado momento. Cada mudança no estado do formulário retorna um novo estado, que mantém a integridade do modelo entre as mudanças. Os formulários reativos são construídos em torno de fluxos observáveis , em que entradas e valores de formulário são fornecidos como fluxos de valores de entrada, que podem ser acessados ​​de forma síncrona. Os formulários reativos também fornecem um caminho direto para o teste, porque você tem certeza de que seus dados são consistentes e previsíveis quando solicitados. Qualquer consumidor dos fluxos tem acesso para manipular esses dados com segurança. Os formulários reativos diferem dos formulários orientados a modelos de maneiras distintas. Os formulários reativos fornecem mais previsibilidade com acesso síncrono ao modelo de dados, imutabilidade com operadores observáveis ​​e rastreamento de alterações através de fluxos observáveis. Os formulários controlados por modelo permitem acesso direto para modificar dados em seu modelo, mas são menos explícitos que os formulários reativos, porque contam com diretivas incorporadas ao modelo, juntamente com dados mutáveis ​​para rastrear alterações de forma assíncrona. Consulte a Visão geral dos formulários para comparações detalhadas entre os dois paradigmas. ### Escolhendo uma abordagem Formulários reativos e formulários controlados por modelo processam e gerenciam dados de formulário de maneira diferente. Cada abordagem oferece vantagens diferentes. * Os formulários reativos fornecem acesso direto e explícito ao modelo de objeto de formulários subjacente. Comparados aos formulários orientados a modelos, eles são mais robustos: são mais escaláveis, reutilizáveis ​​e testáveis. Se os formulários são uma parte essencial do seu aplicativo, ou você já está usando padrões reativos para criar seu aplicativo, use formulários reativos. * Formulários controlados por modelo dependem de diretrizes no modelo para criar e manipular o modelo de objeto subjacente. Eles são úteis para adicionar um formulário simples a um aplicativo, como um formulário de inscrição na lista de emails. Eles são fáceis de adicionar a um aplicativo, mas não são dimensionados tão bem quanto em formas reativas. Se você possui requisitos e lógica de formulário muito básicos que podem ser gerenciados apenas no modelo, os formulários controlados por modelo podem ser uma boa opção. ### Principais diferenças | | REATIVO | ORIENTADO A MODELOS | | ---| ------ | ----------- | | Configuração do modelo de formulário | Explícito, criado na classe de componente | Implícito, criado por diretivas | | Modelo de dados |Estruturado e imutável | Não estruturado e mutável | | Previsibilidade | Síncrono | Assíncrono | | Validação de formulário |Funções | Diretivas | ### Escalabilidade Se os formulários são uma parte central do seu aplicativo, a escalabilidade é muito importante. Ser capaz de reutilizar modelos de formulário entre componentes é fundamental. Formulários reativos são mais escaláveis ​​que formulários controlados por modelo. Eles fornecem acesso direto à API do formulário subjacente e acesso síncrono ao modelo de dados do formulário, facilitando a criação de formulários em grande escala. Os formulários reativos requerem menos configuração para o teste, e o teste não requer um entendimento profundo da detecção de alterações para testar adequadamente as atualizações e a validação do formulário. Os formulários orientados a modelos concentram-se em cenários simples e não são tão reutilizáveis. Eles abstraem a API do formulário subjacente e fornecem apenas acesso assíncrono ao modelo de dados do formulário. A abstração de formulários controlados por modelo também afeta o teste. Os testes dependem profundamente da execução manual da detecção de alterações para serem executados corretamente e exigem mais configurações. --- Acesso direto ao modelo de formulários de forma reativa. ![](https://i.imgur.com/Bl9piKD.png) --- Acesso indireto ao modelo de formulários em um formulário controlado por modelo. ![](https://i.imgur.com/GU6KpgB.png) --- ## Lazy Loading ![](https://i.imgur.com/NzUXCj4.png) **Lazy loading** é o processo de carregamento de módulos (imagens, vídeos, documentos, JS, CSS, etc) sob demanda. Os conceitos mais importantes de desempenho do aplicativo são: *Tempo de Resposta* e *Consumo de Recursos*. É inevitável que isso aconteça. Além disso, um problema pode surgir de qualquer lugar, mas é muito importante encontrá-los e resolvê-los antes que aconteçam. A perspectiva de **Lazy Loading** no Angular ajuda a reduzir ao mínimo o risco de alguns dos problemas de desempenho do aplicativo da web. O **Lazy Loading** faz bem em verificar os conceitos listados acima: * **Tempo de resposta** : é a quantidade de tempo que o aplicativo da web leva para carregar e a interface de IU para responder aos usuários. O carregamento lento otimiza o tempo de resposta dividindo o código e carregando o pacote desejado. * **Consumo de recursos** : os humanos são criaturas impacientes se um site leva mais de 3 segundos para carregar, 70% de nós desistiremos. Os aplicativos da web não devem demorar tanto para carregar. Portanto, para reduzir a quantidade de carregamento de recursos, o carregamento lento carrega o pacote de código necessário por vez. > **O carregamento lento acelera o tempo de carregamento de nosso aplicativo, dividindo-o em vários pacotes e carregando-os sob demanda.** ### Vantagens do carregamento lento: * Alto desempenho em tempo de bootstrap na carga inicial. * Os módulos são agrupados de acordo com sua funcionalidade. * Pacotes de código menores para download no carregamento inicial. * Ative / baixe um módulo de código navegando para uma rota. * O carregamento lento não carrega tudo uma vez, ele carrega apenas o que o usuário espera ver primeiro. ### Como funciona o Lazy Loading? O **Lazy Loading** geralmente é um conceito em que atrasamos o carregamento de um objeto até que ele seja necessário. No Angular, todos os componentes JavaScript declarados na matriz de declarações app.module.tssão agrupados e carregados de uma só vez quando um usuário visita nosso site. ### A estrutura Abaixo a estrutura proposta para projetos de grande porte: ![](https://i.imgur.com/2gDzOXx.png) #### Módulos - Lazy Load Módulos lazy loaded ajudam a diminuir o tempo de inicialização da aplicação. Com o lazy load, o aplicativo não precisa carregar tudo de uma só vez. Ele só vai carregar o que o usuário espera ver. O módulo só irá carregar quando o usuário navegar para sua rota. Perfeito para aplicações grande, combina com o interesse do usuário e organiza a estrutura. Todo o conteúdo do módulo está diretamente relacionado com a rota. Logo faz sentido os componentes estarem dentro do módulo. ![](https://i.imgur.com/zZmoFDb.png) Trabalhar com módulos há ganhos significativos na inicialização da aplicação. É inimaginável uma aplicação Angular de médio porte sem módulos lazy load. E essa estrutura é coesa, mantém os grupos de interesse dentro de um mesmo local. #### Core O core module deve conter serviços singleton, componentes universais e outros recursos em que há uma instância única. Autenticação, header, interceptors são exemplos de componentes que terá apenas uma instância ativa para a aplicação e será utilizado praticamente por todos os modules. #### Shared O shared é onde todos os componentes compartilhados, pipes, filters e services devem ir. O shared pode ser importado em qualquer module. Assim esses itens serão reutilizados. O shared module deve ser independente do restante do aplicativo. Portanto, não deve ter referências de outro módulo.