<?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>DEV Community: Adrián UB</title>
    <description>The latest articles on DEV Community by Adrián UB (@adrianub).</description>
    <link>https://dev.to/adrianub</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%2F438347%2Fd2f8a7b8-a6f8-473a-a698-8742b885acac.png</url>
      <title>DEV Community: Adrián UB</title>
      <link>https://dev.to/adrianub</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adrianub"/>
    <language>en</language>
    <item>
      <title>Como desplegar NestJS en Deta.sh 🚀</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Sun, 27 Feb 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/adrianub/como-desplegar-nestjs-en-detash-2c14</link>
      <guid>https://dev.to/adrianub/como-desplegar-nestjs-en-detash-2c14</guid>
      <description>&lt;p&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%2Ffx3qhgo4fw39r6z46kmy.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%2Ffx3qhgo4fw39r6z46kmy.png" alt="Como desplegar NestJS en Deta.sh 🚀"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Que es Deta.sh?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://deta.sh" rel="noopener noreferrer"&gt;Deta&lt;/a&gt; es una nube gratuita diseñada pensando en la experiencia del desarrollador y del usuario, nos ayuda crear implementaciones de nuestras ideas en la nube más amigable con los desarrolladores, es totalmente gratuita y para siempre.&lt;/p&gt;

&lt;p&gt;En esta podemos desplegar aplicaciones hecha con &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;NodeJs&lt;/a&gt; y &lt;a href="https://www.python.org/" rel="noopener noreferrer"&gt;Python&lt;/a&gt;, donde nos proveen un &lt;a href="https://docs.deta.sh/docs/micros/about" rel="noopener noreferrer"&gt;Micro&lt;/a&gt; por cada aplicación desplegada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creación del proyecto NestJS
&lt;/h2&gt;

&lt;p&gt;Para comenzar a crear nuestro clonaremos el starter de &lt;a href="https://nestjs.com" rel="noopener noreferrer"&gt;NestJS&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/nestjs/typescript-starter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Instalamos las dependencias y vemos que nuestro proyecto corra sin ningun error.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configurar proyecto
&lt;/h2&gt;

&lt;p&gt;Primero crearemos nuestro punto de entrada en &lt;code&gt;src/index.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ExpressAdapter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/platform-express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createNestServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expressInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ExpressAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expressInstance&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;createNestServer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Crearemos un archivo llamado &lt;code&gt;index.js&lt;/code&gt; en el root de nuestra aplicación:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dist/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;nest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;nest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;nest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Desplegar proyecto
&lt;/h2&gt;

&lt;p&gt;Para poder desplegar nuestra aplicación necesitamos correr los siguientes comandos.&lt;/p&gt;
&lt;h3&gt;
  
  
  Compilar
&lt;/h3&gt;

&lt;p&gt;Escribe el siguiente comando en la terminal para compilar tu proyecto:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Iniciar sesión en Deta
&lt;/h3&gt;

&lt;p&gt;Para iniciar sesión en Deta necesitamos correr el siguiente comando:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deta login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Crear un Micro
&lt;/h3&gt;

&lt;p&gt;Creamos un nuevo micro desde una carpeta anterior a nuestro proyecto:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deta new &lt;span class="nt"&gt;--node&lt;/span&gt; nombre-del-proyecto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Deploy 🚀
&lt;/h3&gt;

&lt;p&gt;Y por ultimo desplegamos el proyecto ejecutando el siguiente comando en el root de la aplicación:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deta deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Luego puedes visitar la url creada por Deta y sacar provecho&lt;/p&gt;

&lt;p&gt;Ejemplo: &lt;a href="https://7dug2x.deta.dev/" rel="noopener noreferrer"&gt;https://7dug2x.deta.dev/&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/adrian-ub" rel="noopener noreferrer"&gt;
        adrian-ub
      &lt;/a&gt; / &lt;a href="https://github.com/adrian-ub/nest-deta" rel="noopener noreferrer"&gt;
        nest-deta
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Template for blog post  https://adrianub.dev/blog/desplegar-nestjs-en-detash
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Description&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/nestjs/nest" rel="noopener noreferrer"&gt;Nest&lt;/a&gt; framework TypeScript starter repository.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;$ yarn&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Running the app&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; development&lt;/span&gt;
$ yarn start

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; watch mode&lt;/span&gt;
$ yarn run start:dev

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; production mode&lt;/span&gt;
$ yarn run start:prod&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Test&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; unit tests&lt;/span&gt;
$ yarn run &lt;span class="pl-c1"&gt;test&lt;/span&gt;

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; e2e tests&lt;/span&gt;
$ yarn run test:e2e

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; test coverage&lt;/span&gt;
$ yarn run test:cov&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Build and Deploy&lt;/h2&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;These steps assume you already have added &lt;em&gt;Deta Micros&lt;/em&gt; to your Project.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://deta.sh" rel="nofollow noopener noreferrer"&gt;https://deta.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.deta.sh/docs/micros/getting_started" rel="nofollow noopener noreferrer"&gt;https://docs.deta.sh/docs/micros/getting_started&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; build&lt;/span&gt;
$ yarn build

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; deploy&lt;/span&gt;
$ deta deploy&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;License&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;This Project is &lt;a href="https://github.com/adrian-ub/nest-detaLICENSE.md" rel="noopener noreferrer"&gt;MIT licensed&lt;/a&gt;.&lt;br&gt;
Please review the &lt;a href="https://github.com/nestjs/nest/blob/master/LICENSE" rel="noopener noreferrer"&gt;License of NestJS&lt;/a&gt; which this example is based on.&lt;br&gt;
Based on &lt;a href="https://github.com/nestjs/typescript-starter.git" rel="noopener noreferrer"&gt;nestjs/typescript-starter&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/adrian-ub/nest-deta" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>nestjs</category>
      <category>deta</category>
    </item>
    <item>
      <title>Refactorización: Guard Clauses</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Fri, 01 Oct 2021 18:34:34 +0000</pubDate>
      <link>https://dev.to/adrianub/refactorizacion-guard-clauses-d36</link>
      <guid>https://dev.to/adrianub/refactorizacion-guard-clauses-d36</guid>
      <description>&lt;p&gt;Es probable que en algún momento de su carrera de programación haya escrito declaraciones lógicas condicionales masivas con muchos niveles de declaraciones &lt;code&gt;if&lt;/code&gt; y &lt;code&gt;else if&lt;/code&gt; anidadas. Al principio puede parecer una gran idea, ya que encaja perfectamente con la lógica que está tratando de hacer cumplir, pero luego pasa un mes y necesita hacer cambios en ese bloque condicional masivo. Lo más probable es que le haya llevado mucho tiempo analizar y comprender la lógica condicional, ya que estaba llena de múltiples niveles de anidamiento y sus nuevos cambios probablemente eran muy propensos a errores. Puede parecer que no hay forma de evitar este problema, pero ahí es donde entran en juego las cláusulas de protección.&lt;/p&gt;

&lt;p&gt;Los principales problemas que aparecen en el código en el que no se aplica la técnica de las cláusulas de protección son los siguientes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Indentación excesiva&lt;/strong&gt; — el uso excesivo de la estructura de control si está anidada significa que hay un alto nivel de indentación que dificulta la lectura del código.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relación entre if-else&lt;/strong&gt; — cuando hay una gran cantidad de fragmentos de código separados entre if-else, que están conceptualmente relacionados entre sí, es necesario realizar la lectura del código saltando entre las diferentes partes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Esfuerzo mental&lt;/strong&gt; — una consecuencia de los diferentes saltos en el código fuente provoca que se genere un esfuerzo extra en la generación de código.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Aplicaciones prácticas
&lt;/h2&gt;

&lt;p&gt;La aplicación práctica de una cláusula de guarda es el siguiente caso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function doSomething() {
  if (everythingIsGood()) {
    /**
     * ¡¡¡Mucho código aquí !!!
     */
    return SOME_VALUE;
  } else {
    return ANOTHER_VALUE; // un caso especial
  }
}

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

&lt;/div&gt;



&lt;p&gt;En este caso, y la mayoría de las veces, debe invertir la lógica para evitar usar la palabra reservada &lt;code&gt;else&lt;/code&gt;. El código anterior se reescribiría de la siguiente manera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function doSomething() {
  if (!everythingIsGood()) {
    // esta es su cláusula de protección
    return ANOTHER_VALUE;
  }

  /**
   * ¡¡¡Mucho código aquí !!!
   */
  return SOME_VALUE;
}

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

&lt;/div&gt;



&lt;p&gt;Por tanto, los casos particulares que provoquen una salida del método se colocarían al inicio del método y actuarían como guardas de forma que se evite continuar por el flujo satisfactorio del método.&lt;/p&gt;

&lt;p&gt;De esta forma, el método es de fácil lectura ya que los casos particulares se encuentran al inicio del mismo y el caso de uso de flujo satisfactorio es el cuerpo del método.&lt;/p&gt;

&lt;p&gt;Echemos un vistazo a un ejemplo un poco más complejo sobre el cálculo de los deducibles del seguro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getInsuranceDeductible(insurance) {
  if (insurance.covered) {
    if (insurance.majorRepair) {
      return 500;
    } else if (insurance.mediumRepair) {
      return 300;
    } else {
      return 100;
    }
  } else {
    return 0;
  }
}

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

&lt;/div&gt;



&lt;p&gt;Esta es una función muy simple, pero la lógica anidada &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else if&lt;/code&gt; es difícil de seguir a primera vista. Para limpiar esto, podemos usar nuevamente cláusulas de protección.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getInsuranceDeductible(insurance) {
  if (!insurance.covered) return 0;
  if (insurance.majorRepair) return 500;
  if (insurance.mediumRepair) return 300;

  return 100;
}

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

&lt;/div&gt;



&lt;p&gt;Esta función es mucho más corta que la función anterior y mucho más fácil de entender, ya que toda la lógica es autónoma y no está anidada entre sí.&lt;/p&gt;




&lt;p&gt;Imagina que tienes que crear un método que calcule el costo del seguro médico en el que se recibe el ID de usuario como parámetro.&lt;/p&gt;

&lt;p&gt;Se realiza una búsqueda en una base de datos utilizando este ID para recuperar un usuario. Si el usuario no existe, se lanzará una excepción llamada &lt;code&gt;UserNotFoundException&lt;/code&gt;. Si el usuario existe en el sistema, el siguiente paso es verificar que el seguro médico del usuario corresponda a alguno de los que son válidos para este algoritmo: Allianz o AXA. Si el seguro no es válido, se debe devolver una excepción llamada &lt;code&gt;UserInsuranceNotFoundException&lt;/code&gt;. Finalmente, este algoritmo solo es válido para usuarios que sean de nacionalidad colombiana. Por lo tanto, debe verificar nuevamente si el usuario es colombiano para realizar el cálculo del seguro o devolver una excepción llamada &lt;code&gt;UserIsNotColombianException&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function calculateInsurance(userId: number) {
  const user = myDb.findOne(userId);

  if (user) {
    if (user.insurance === 'Allianz' || user.insurance === 'AXA') {
      if (user.nationality === 'Colombian') {
        const value = any;
        /**
         * Algoritmo complejo
         */
        return value;
      } else {
        throw new UserIsNotColombianException(user);
      }
    } else {
      throw new UserInsuranceNotFoundException(user);
    }
  } else {
    throw new UserNotFoundException('User NotFound');
  }
}

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

&lt;/div&gt;



&lt;p&gt;Como puede ver, el código tiene muchos niveles de indentación. A continuación se muestra la misma versión del algoritmo anterior, pero se ha aplicado la técnica de las cláusulas de protección. Esta técnica permite que el código sea más legible. Tenga en cuenta que se han aplicado tres cláusulas de protección que permiten generar rutas alternativas (lanzar excepciones) que no interfieren en el resultado del algoritmo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function calculateInsurance(userId: number) {
  const user = myDb.findOne(userId);

  if (!user) {
    throw new UserNotFoundException('User NotFound');
  }

  if (!(user.insurance === 'Allianz' || user.insurance === 'AXA')) {
    throw new UserInsuranceNotFoundException(user);
  }

  if (user.nationality !== 'Colombian') {
    throw new UserIsNotColombianException(user);
  }

  const value = any;
  /**
   * Algoritmo complejo
   */
  return value;
}

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

&lt;/div&gt;



&lt;p&gt;Algunas cuestiones que deben resolverse:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;¿Por qué no hay casos de if-else if?&lt;/p&gt;

&lt;p&gt;¡Deja de pensar! Si su código requiere casos como el &lt;code&gt;else if&lt;/code&gt;, es porque está incumpliendo el Principio de Responsabilidad Única y el código toma decisiones de nivel superior, que deben refactorizarse.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Las condiciones negativas no se comprenden bien.&lt;/p&gt;

&lt;p&gt;Para ello contamos con otra técnica de refactorización llamada método extract, que consiste en extraer código en funciones para su reutilización o comprensión lectora. En el siguiente ejemplo, modificamos el ejemplo anterior para crear métodos que permitan una mejor lectura y comprensión del código.&lt;/p&gt;

&lt;p&gt;En el uso de una cláusula de protección, la lógica de las condiciones normalmente se invierte y, dependiendo de la complejidad de la condición, es bastante complejo entender qué se está evaluando en esa condición.&lt;/p&gt;

&lt;p&gt;Por eso es una buena práctica extraer la lógica de las condiciones en pequeñas funciones que permitan una mayor legibilidad del código (y, por supuesto, encontrar errores en ellas) ya que la responsabilidad de evaluar la condición se está delegando a una función específica.&lt;/p&gt;

&lt;p&gt;Para nuestro ejemplo de seguro médico podemos generar los siguientes métodos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function isValidInsurance({ insurance }: User): boolean {
  return insurance === 'Allianz' || insurance === 'AXA';
}

function isColombian({ nationality }: User): boolean {
  return nationality === 'Colombian';
}

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

&lt;/div&gt;



&lt;p&gt;No es necesario crear una función para comprobar si el usuario existe, ya que basta con comprobar que el usuario es diferente de nulo o indefinido. Por tanto, el código resultante sería el siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function calculateInsurance(userId: number) {
  const user = myDb.findOne(userId);

  if (!user) {
    throw new UserNotFoundException('User NotFound');
  }

  if (!isValidInsurance(user)) {
    throw new UserInsuranceNotFoundException(user);
  }

  if (!isColombian(user)) {
    throw new UserIsNotColombianException(user);
  }

  const value = any;
  /**
   * Algoritmo complejo
   */
  return value;
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Resumen
&lt;/h2&gt;

&lt;p&gt;Existen muchas prácticas para mejorar la calidad del código. Lo más importante que hay que aprender a la hora de aplicar técnicas de refactorización es que deben centrarse en dos puntos, principalmente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Desacoplar el código&lt;/strong&gt; — esto permite pequeños cambios que no causan grandes cambios encadenados en todo el proyecto de software.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Legibilidad&lt;/strong&gt; — es muy importante que los desarrolladores comprendan que la mayor parte del tiempo de su trabajo se basa en la lectura de código y, probablemente, en código escrito por otro desarrollador. Es muy beneficioso en costo/desarrollo que un desarrollador no pierda tiempo entendiendo la lógica elemental porque no es fácil de leer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La refactorización comienza desde el punto más elemental, un simple &lt;code&gt;if&lt;/code&gt;, hasta un patrón de arquitectura. Es importante cuidar todos los aspectos de nuestro desarrollo de software.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Crear controles de formulario personalizados usando ControlValueAccessor en Angular</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Sun, 12 Sep 2021 19:12:40 +0000</pubDate>
      <link>https://dev.to/adrianub/crear-controles-de-formulario-personalizados-usando-controlvalueaccessor-en-angular-2ip9</link>
      <guid>https://dev.to/adrianub/crear-controles-de-formulario-personalizados-usando-controlvalueaccessor-en-angular-2ip9</guid>
      <description>&lt;p&gt;¿Cómo crear controles de formulario personalizados en Angular usando ControlValueAccessor? Podemos crear componentes de formulario personalizados y conectarlos a formularios basados ​​en plantillas o formularios reactivos.&lt;/p&gt;

&lt;p&gt;Entonces, cuando digo controles de formulario personalizados, me refiero a aquellos elementos que no son sus controles típicos, como inputs, radio buttons o checkboxes. Por ejemplo, un componente de clasificación con estrellas. Estos no están disponibles de fábrica.&lt;/p&gt;

&lt;p&gt;También podemos crear secciones en un formulario como componentes secundarios que luego se pueden usar como controles de formulario personalizados. De esta manera, las formas más grandes se pueden dividir en partes manejables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elementos de formulario personalizados
&lt;/h2&gt;

&lt;p&gt;Cuando escuchemos el término formulario, estaríamos pensando en inputs y tal vez en algunos checkboxes, etc. Pero cuando se trata de formularios realmente grandes en los que tenemos muchos botones, listas y selecciones personalizados, todo el formulario se volverá muy complejo y manejar esto sería un problema.&lt;/p&gt;

&lt;p&gt;Cuando hay muchos elementos de formulario personalizados o cuando el formulario comienza a crecer, probablemente sea una buena idea dividirlo en secciones más pequeñas. Colocar todo en una sola plantilla lo haría realmente complicado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Control de formulario personalizado en Angular
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://angular.io/api/forms/ControlValueAccessor"&gt;ControlValueAccessor&lt;/a&gt; es una interfaz incluida en Angular. Actúa como un puente entre los elementos DOM y la API de forma angular.&lt;/p&gt;

&lt;p&gt;Entonces, si tiene un elemento personalizado que le gustaría conectar a su formulario, debe hacer uso de ControlValueAccessor para que el elemento sea compatible con la API de Angular Forms. Hacerlo permitirá que el elemento se conecte usando &lt;code&gt;ngModel&lt;/code&gt; (Formularios controlados por plantillas) o &lt;code&gt;formControl&lt;/code&gt; (Formularios reactivos).&lt;/p&gt;

&lt;p&gt;Echemos un vistazo a cómo creamos un control de formulario personalizado&lt;/p&gt;

&lt;p&gt;Cuando comencé con Angular, no sabía que existía algo como esto. Recuerdo cuando escribí componentes secundarios para formularios y usé &lt;code&gt;@Input()&lt;/code&gt; y &lt;code&gt;@Output()&lt;/code&gt; para recibir y enviar valores de formulario al componente de formulario principal. Solía ​​escuchar los cambios en el componente hijo y luego emitir los valores al padre.&lt;/p&gt;

&lt;p&gt;En el padre, los valores se tomarán y usarán para parchear el formulario. Esto fue hasta que me encontré con el ControlValueAccessor. No más inputs y outputs, todo simplemente funciona.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 1: configuración del proyecto
&lt;/h2&gt;

&lt;p&gt;Primero, cree un nuevo &lt;code&gt;RatingInputComponent&lt;/code&gt;. Esto se puede lograr con &lt;code&gt;@angular/cli&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng generate component rating-input --inline-template --inline-style

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

&lt;/div&gt;



&lt;p&gt;Esto agregará el nuevo componente a las &lt;code&gt;declarations&lt;/code&gt; de la aplicación y producirá un archivo &lt;code&gt;rating-input.component.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-rating-input',
  template: ` &amp;lt;p&amp;gt;rating-input works!&amp;lt;/p&amp;gt; `,
  styles: [],
})
export class RatingInputComponent implements OnInit {
  constructor() {}

  ngOnInit(): void {}
}

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

&lt;/div&gt;



&lt;p&gt;Agregamos la plantilla, los estilos y la lógica:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component } from '@angular/core';

@Component({
  selector: 'app-rating-input',
  template: `
    &amp;lt;ng-container *ngFor="let starred of stars; let i = index"&amp;gt;
      &amp;lt;span (click)="rate(i + (starred ? (value &amp;gt; i + 1 ? 1 : 0) : 1))"&amp;gt;
        &amp;lt;ng-container *ngIf="starred; else noStar"&amp;gt;⭐&amp;lt;/ng-container&amp;gt;
        &amp;lt;ng-template #noStar&amp;gt;·&amp;lt;/ng-template&amp;gt;
      &amp;lt;/span&amp;gt;
    &amp;lt;/ng-container&amp;gt;
  `,
  styles: [
    `
      span {
        display: inline-block;
        width: 25px;
        line-height: 25px;
        text-align: center;
        cursor: pointer;
      }
    `,
  ],
})
export class RatingInputComponent {
  stars: boolean[] = Array(5).fill(false);

  get value(): number {
    return this.stars.reduce((total, starred) =&amp;gt; {
      return total + (starred ? 1 : 0);
    }, 0);
  }

  rate(rating: number) {
    this.stars = this.stars.map((_, i) =&amp;gt; rating &amp;gt; i);
  }
}

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

&lt;/div&gt;



&lt;p&gt;Podemos obtener el &lt;code&gt;value&lt;/code&gt; del componente (&lt;code&gt;0&lt;/code&gt; a &lt;code&gt;5&lt;/code&gt;) y establecer el valor del componente llamando a la función de &lt;code&gt;rate&lt;/code&gt; o haciendo clic en el número de estrellas deseado.&lt;/p&gt;

&lt;p&gt;Puede agregar el componente a la aplicación: &lt;code&gt;src/app/app.component.html&lt;/code&gt;&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;app-rating-input&amp;gt;&amp;lt;/app-rating-input&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Y ejecute la aplicación:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Esto es genial, pero no podemos simplemente agregar esta entrada a un formulario y esperar que todo funcione. Necesitamos convertirlo en un &lt;code&gt;ControlValueAccessor&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implemente la interface ControlValueAccessor
&lt;/h2&gt;

&lt;p&gt;Implemente la interfaz en el componente personalizado. La interfaz nos pediría que agreguemos algunos métodos en nuestra clase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface ControlValueAccessor {
  writeValue(obj: any): void
  registerOnChange(fn: any): void
  registerOnTouched(fn: any): void
  setDisabledState(isDisabled: boolean)?: void
}

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

&lt;/div&gt;



&lt;p&gt;Veamos qué está haciendo cada uno de los métodos. Una vez que tengamos claro cómo están las cosas, podemos sumergirnos en la implementación.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;writeValue()&lt;/code&gt; - la API de formularios llama a esta función para actualizar el valor del elemento. Cuando el valor de ngModel o formControl cambia, se llama a esta función y se pasa el último valor como argumento de la función. Podemos utilizar el último valor y realizar cambios en el componente. (&lt;a href="https://angular.io/api/forms/ControlValueAccessor#writevalue"&gt;referencia&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;registerOnChange()&lt;/code&gt; - obtenemos acceso a una función en el argumento que se puede guardar en una variable local. Entonces esta función se puede llamar cuando hay algún cambio en el valor de nuestro control de formulario personalizado. (&lt;a href="https://angular.io/api/forms/ControlValueAccessor#registerOnChange"&gt;referencia&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;registerOnTouched()&lt;/code&gt; - obtenemos acceso a otra función que se puede utilizar para actualizar el estado del formulario ha sido tocado (&lt;code&gt;touched&lt;/code&gt;). Entonces, cuando el usuario interactúa con nuestro elemento de formulario personalizado, podemos llamar a la función guardada para que Angular sepa que se ha interactuado con el elemento. (&lt;a href="https://angular.io/api/forms/ControlValueAccessor#registerOnTouched"&gt;referencia&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setDisabledState()&lt;/code&gt; - esta función será llamada por la API de formularios cuando se cambie el estado deshabilitado (&lt;code&gt;disabled&lt;/code&gt;). Podemos obtener el estado actual y actualizar el estado del control de formulario personalizado. (&lt;a href="https://angular.io/api/forms/ControlValueAccessor#setDisabledState"&gt;referencia&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Una vez que implementamos estas funciones, el siguiente paso es proporcionar el token &lt;code&gt;NG_VALUE_ACCESSOR&lt;/code&gt; en la matriz de proveedores del componente así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const CONTROL_VALUE_ACCESSOR: Provider = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() =&amp;gt; RatingInputComponent),
  multi: true,
};

@Component({
  selector: 'app-rating-input',
  template: ` &amp;lt;p&amp;gt;rating-input works!&amp;lt;/p&amp;gt; `,
  providers: [CONTROL_VALUE_ACCESSOR], // &amp;lt;-- agregar aquí
})
export class RatingInputComponent implements ControlValueAccessor {}

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Aquí creé una constante de proveedor y luego la pasé a los &lt;code&gt;providers&lt;/code&gt;. También puede ver el uso de &lt;code&gt;forwardRef&lt;/code&gt; aquí (&lt;a href="https://angular.io/api/core/forwardRef"&gt;referencia&lt;/a&gt;). Es necesario porque nos referimos a la clase &lt;code&gt;RatingInputComponent&lt;/code&gt; que no está definida antes de su referencia.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Entonces, ahora que sabemos lo que hace cada una de estas funciones, podemos comenzar a implementar nuestro elemento de formulario personalizado.&lt;/p&gt;

&lt;p&gt;Volvamos a &lt;code&gt;rating-input.component.ts&lt;/code&gt; en el editor de código y realicemos los siguientes cambios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, forwardRef, HostBinding, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

const CONTROL_VALUE_ACCESSOR: Provider = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() =&amp;gt; RatingInputComponent),
  multi: true,
};

@Component({
  selector: 'app-rating-input',
  template: `
    &amp;lt;ng-container *ngFor="let starred of stars; let i = index"&amp;gt;
      &amp;lt;span
        (click)="onTouched(); rate(i + (starred ? (value &amp;gt; i + 1 ? 1 : 0) : 1))"
      &amp;gt;
        &amp;lt;ng-container *ngIf="starred; else noStar"&amp;gt;⭐&amp;lt;/ng-container&amp;gt;
        &amp;lt;ng-template #noStar&amp;gt;·&amp;lt;/ng-template&amp;gt;
      &amp;lt;/span&amp;gt;
    &amp;lt;/ng-container&amp;gt;
  `,
  styles: [
    `
      span {
        display: inline-block;
        width: 25px;
        line-height: 25px;
        text-align: center;
        cursor: pointer;
      }
    `,
  ],
  providers: [CONTROL_VALUE_ACCESSOR],
})
export class RatingInputComponent implements ControlValueAccessor {
  stars: boolean[] = Array(5).fill(false);

  // Permita que el input esté deshabilitado, y cuando lo esté, hágalo algo transparente.
  @Input() disabled = false;
  @HostBinding('style.opacity')
  get opacity() {
    return this.disabled ? 0.25 : 1;
  }

  // Función para llamar cuando cambia la calificación.
  onChange = (rating: number) =&amp;gt; {};

  // Función para llamar cuando se toca el input (cuando se hace clic en una estrella).
  onTouched = () =&amp;gt; {};

  get value(): number {
    return this.stars.reduce((total, starred) =&amp;gt; {
      return total + (starred ? 1 : 0);
    }, 0);
  }

  rate(rating: number) {
    if (!this.disabled) {
      this.writeValue(rating);
    }
  }

  // Permite que Angular actualice el modelo (rating).
  // Actualice el modelo y los cambios necesarios para la vista aquí.
  writeValue(rating: number): void {
    this.stars = this.stars.map((_, i) =&amp;gt; rating &amp;gt; i);
    this.onChange(this.value);
  }

  // Permite a Angular registrar una función para llamar cuando cambia el modelo (rating).
  // Guarde la función como una propiedad para llamar más tarde aquí.
  registerOnChange(fn: (rating: number) =&amp;gt; void): void {
    this.onChange = fn;
  }

  // Permite a Angular registrar una función para llamar cuando se ha tocado el input.
  // Guarde la función como una propiedad para llamar más tarde aquí.
  registerOnTouched(fn: () =&amp;gt; void): void {
    this.onTouched = fn;
  }

  // Permite que Angular deshabilite el input.
  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }
}

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

&lt;/div&gt;



&lt;p&gt;Ahora puede desactivar los controles del input, agregar un &lt;code&gt;[(ngModel)]&lt;/code&gt; o un &lt;code&gt;formControlName&lt;/code&gt;:&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;app-rating-input [disabled]="true"&amp;gt;&amp;lt;/app-rating-input&amp;gt;

&amp;lt;app-rating-input [(ngModel)]="rating"&amp;gt;&amp;lt;/app-rating-input&amp;gt;

&amp;lt;form [formGroup]="reactiveForm"&amp;gt;
  &amp;lt;app-rating-input formControlName="rating"&amp;gt;&amp;lt;/app-rating-input&amp;gt;
&amp;lt;/form&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;¡En este punto podemos decir que nuestro &lt;code&gt;RatingInputComponent&lt;/code&gt; es un componente de formulario personalizado! Funcionará como cualquier otro input nativo (¡Angular proporciona &lt;code&gt;ControlValueAccessors&lt;/code&gt; para esos!) En formas reactivas o basadas en plantillas.&lt;/p&gt;

&lt;p&gt;Angular hace que sea realmente fácil implementar el control de formulario personalizado usando &lt;code&gt;ControlValueAccessor&lt;/code&gt;. Al implementar algunos métodos, podemos conectar directamente nuestro componente a un &lt;code&gt;formulario reactivo&lt;/code&gt; o &lt;code&gt;Template Driven&lt;/code&gt; con facilidad.&lt;/p&gt;

&lt;p&gt;Podemos escribir todo tipo de elementos de formas asombrosas y usarlos sin escribir lógica para manejar la comunicación entre padres e hijos. Deje que la API de formularios haga la magia por nosotros.&lt;/p&gt;

&lt;p&gt;También podemos utilizar este enfoque para dividir secciones del formulario en su propio componente individual. De esta manera, si el formulario es grande/complejo, podemos dividirlo en componentes más pequeños que se pueden administrar fácilmente.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How to add brand colors on TailwindCSS</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Mon, 05 Jul 2021 21:40:19 +0000</pubDate>
      <link>https://dev.to/ub/how-to-add-brands-colors-on-tailwindcss-45f5</link>
      <guid>https://dev.to/ub/how-to-add-brands-colors-on-tailwindcss-45f5</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ublabs"&gt;
        ublabs
      &lt;/a&gt; / &lt;a href="https://github.com/ublabs/tailwindcss-brand-colors"&gt;
        tailwindcss-brand-colors
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Tailwind plugin for adding brands colors.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h3&gt;

TailwindCSS Brand Colors
&lt;/h3&gt;
&lt;p&gt;
  Tailwind plugin for adding brands colors.
&lt;/p&gt;




&lt;h2&gt;
Install&lt;/h2&gt;

&lt;div class="highlight highlight-source-shell position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install @ublabs/tailwindcss-brand-colors&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;div class="highlight highlight-source-shell position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn add @ublabs/tailwindcss-brand-colors&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add the plugin to your tailwind.config.js file:&lt;/p&gt;

&lt;div class="highlight highlight-source-js position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// tailwind.config.js&lt;/span&gt;
&lt;span class="pl-smi"&gt;module&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;exports&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;theme&lt;/span&gt;: &lt;span class="pl-kos"&gt;{&lt;/span&gt;
    &lt;span class="pl-c"&gt;// ...&lt;/span&gt;
  &lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;plugins&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;
    &lt;span class="pl-c"&gt;//  for all list&lt;/span&gt;
    &lt;span class="pl-en"&gt;require&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'@ublabs/tailwindcss-brand-colors'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    &lt;span class="pl-c"&gt;// select the brands&lt;/span&gt;
    &lt;span class="pl-en"&gt;require&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'@ublabs/tailwindcss-brand-colors'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s"&gt;'angular'&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s"&gt;'tailwindcss'&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    &lt;span class="pl-c"&gt;// ...&lt;/span&gt;
  &lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://tailwindcss-brand-colors.pages.dev/" rel="nofollow"&gt;See the list of all brand colors available here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
How to add a new brand color?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Fork/Clone Repository&lt;/p&gt;
&lt;div class="highlight highlight-source-shell position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/YOUR-USERNAME/tailwindcss-brand-colors&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Dependencies&lt;/p&gt;
&lt;div class="highlight highlight-source-shell position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn install&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select Color&lt;/p&gt;
&lt;p&gt;Ex: &lt;code&gt;#111827&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set Brand Color&lt;/p&gt;
&lt;div class="highlight highlight-source-shell position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn nx workspace-schematic add-brand --name=&lt;span class="pl-k"&gt;&amp;lt;&lt;/span&gt;brand-name&lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt; --hex=&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt;111827&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Credits&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/adrian-ub"&gt;Adrián UB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ublabs/tailwindcss-brand-colors../../contributors"&gt;All Contributors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Inspired by &lt;a href="https://github.com/simple-icons/simple-icons"&gt;Simple Icons&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
License&lt;/h2&gt;
&lt;p&gt;The MIT License (MIT). Please see &lt;a href="https://github.com/ublabs/tailwindcss-brand-colorsLICENSE.md"&gt;License File&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ublabs/tailwindcss-brand-colors"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>tailwindcss</category>
      <category>plugin</category>
    </item>
    <item>
      <title>Bordes rellenables con TailwindCSS</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Mon, 19 Apr 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/adrianub/bordes-rellenables-con-tailwindcss-59he</link>
      <guid>https://dev.to/adrianub/bordes-rellenables-con-tailwindcss-59he</guid>
      <description>&lt;p&gt;Para una mejor visualización, &lt;a href="https://adrianub.dev/blog/bordes-rellenables-con-tailwindcss"&gt;visitar página web&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iniciemos
&lt;/h2&gt;

&lt;p&gt;En primer lugar, comencemos creando una tarjeta simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"block max-w-md mx-auto bg-white border border-gray-400 rounded shadow-sm"&lt;/span&gt;
  &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"View item"&lt;/span&gt;
  &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"View item"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center justify-between p-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pr-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h6&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mb-2 font-semibold leading-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        El universo es un lugar bastante grande
      &lt;span class="nt"&gt;&amp;lt;/h6&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-sm text-gray-900"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Es mucho mejor captar el universo como realmente es que persistir en la
        ilusión, por satisfactorio y reconfortante que sea.
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center justify-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt;
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-3 text-gray-700 transition-colors duration-300 group-hover:text-indigo-600"&lt;/span&gt;
        &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;
        &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 12 12"&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt;
          &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M9.707,5.293l-5-5A1,1,0,0,0,3.293,1.707L7.586,6,3.293,10.293a1,1,0,1,0,1.414,1.414l5-5A1,1,0,0,0,9.707,5.293Z"&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;En el siguiente paso, agregaremos los bordes mágicos (verifique el efecto de desplazamiento):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative block max-w-md mx-auto overflow-hidden bg-white border border-gray-400 rounded shadow-sm group"&lt;/span&gt;
  &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"View item"&lt;/span&gt;
  &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"View item"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute bottom-0 left-0 w-full h-1 duration-300 origin-left transform scale-x-0 bg-indigo-600 group-hover:scale-x-100"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute bottom-0 left-0 w-1 h-full duration-300 origin-bottom transform scale-y-0 bg-indigo-600 group-hover:scale-y-100"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute top-0 left-0 w-full h-1 duration-300 origin-right transform scale-x-0 bg-indigo-600 group-hover:scale-x-100"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute bottom-0 right-0 w-1 h-full duration-300 origin-top transform scale-y-0 bg-indigo-600 group-hover:scale-y-100"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center justify-between p-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pr-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h6&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mb-2 font-semibold leading-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        El universo es un lugar bastante grande
      &lt;span class="nt"&gt;&amp;lt;/h6&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-sm text-gray-900"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Es mucho mejor captar el universo como realmente es que persistir en la
        ilusión, por satisfactorio y reconfortante que sea.
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center justify-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt;
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-3 text-gray-700 transition-colors duration-300 group-hover:text-indigo-600"&lt;/span&gt;
        &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;
        &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 12 12"&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt;
          &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M9.707,5.293l-5-5A1,1,0,0,0,3.293,1.707L7.586,6,3.293,10.293a1,1,0,1,0,1.414,1.414l5-5A1,1,0,0,0,9.707,5.293Z"&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Observe que hemos agregado 4 DIV absolutos, que se estiran al pasar el mouse. No olvide agregar las clases &lt;code&gt;relative&lt;/code&gt; y &lt;code&gt;group&lt;/code&gt; al contenedor principal.&lt;/p&gt;

&lt;p&gt;Además, necesitaremos agregar la variante de desplazamiento de grupo a la propiedad de escala en nuestra configuración de Tailwind:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;responsive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;focus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;group-hover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;El último paso es hacer que los bordes se vean más delgados. Para lograr esto, agregaremos un pequeño relleno de 1 px al contenedor principal y un fondo blanco al contenido. Como beneficio adicional, también podríamos escalar la carta y aumentar su sombra al pasar el mouse.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative block max-w-md p-px mx-auto overflow-hidden transition duration-300 transform bg-white border border-gray-400 rounded shadow-sm hover:scale-105 group hover:shadow-xl"&lt;/span&gt;
  &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"View item"&lt;/span&gt;
  &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"View item"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute bottom-0 left-0 w-full h-1 duration-300 origin-left transform scale-x-0 bg-indigo-600 group-hover:scale-x-100"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute bottom-0 left-0 w-1 h-full duration-300 origin-bottom transform scale-y-0 bg-indigo-600 group-hover:scale-y-100"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute top-0 left-0 w-full h-1 duration-300 origin-right transform scale-x-0 bg-indigo-600 group-hover:scale-x-100"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute bottom-0 right-0 w-1 h-full duration-300 origin-top transform scale-y-0 bg-indigo-600 group-hover:scale-y-100"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative flex items-center justify-between p-5 bg-white rounded-sm"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pr-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h6&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mb-2 font-semibold leading-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        El universo es un lugar bastante grande
      &lt;span class="nt"&gt;&amp;lt;/h6&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-sm text-gray-900"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Es mucho mejor captar el universo como realmente es que persistir en la
        ilusión, por satisfactorio y reconfortante que sea.
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center justify-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt;
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-3 text-gray-700 transition-colors duration-300 group-hover:text-indigo-600"&lt;/span&gt;
        &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;
        &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 12 12"&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt;
          &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M9.707,5.293l-5-5A1,1,0,0,0,3.293,1.707L7.586,6,3.293,10.293a1,1,0,1,0,1.414,1.414l5-5A1,1,0,0,0,9.707,5.293Z"&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;¡Y eso es!&lt;/strong&gt; Toma el código y úsalo en tus increíbles proyectos.&lt;/p&gt;

</description>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Combinando múltiples flujos Http con RxJS Observables en Angular</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Thu, 15 Apr 2021 00:56:11 +0000</pubDate>
      <link>https://dev.to/adrianub/combinando-multiples-flujos-http-con-rxjs-observables-en-angular-5co6</link>
      <guid>https://dev.to/adrianub/combinando-multiples-flujos-http-con-rxjs-observables-en-angular-5co6</guid>
      <description>&lt;p&gt;Veamos cómo podemos combinarlos y encadenarlos para fusionar múltiples flujos de datos Http y obtener lo que necesitamos.&lt;/p&gt;

&lt;p&gt;Lo primero que debemos entender es que el servicio HttpClient en Angular devuelve Observables fríos. ¿Qué significa "frío"? Según la &lt;a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md#cold-vs-hot-observables"&gt;definición&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Los observables fríos comienzan a ejecutarse tras la suscripción, es decir, la secuencia observable solo comienza a enviar valores a los observadores cuando se llama a Subscribe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Una mejor práctica, de hecho, es mantener toda la lógica de manipulación del flujo dentro de nuestro servicio y devolver el Observable, que el controlador puede suscribir.&lt;/p&gt;

&lt;p&gt;A continuación, se muestra un ejemplo básico de servicio con una llamada &lt;code&gt;Http&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AuthorService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/authors/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;El controlador debe llamar al servicio, así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-author&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./author.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AuthorComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;authorService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthorService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nx"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Will return:

{
  id: 1,
  first_name: 'Adrián',
  last_name: 'UB'
}

*/&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Ok, ahora veamos algo más avanzado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combinando Observables en paralelo
&lt;/h2&gt;

&lt;p&gt;Desde la versión 5.5 de RxJs, necesitamos usar la función &lt;code&gt;pipe&lt;/code&gt; para combinar Observables. Acepta tantos operadores pipetables como necesitemos, separados por una coma.&lt;/p&gt;

&lt;p&gt;Imagine que desea obtener los datos de un autor y sus libros, pero para obtener los libros debe llamar a un punto final diferente, como &lt;code&gt;/authors/1/books&lt;/code&gt;. Debe realizar las dos llamadas y combinarlas en una sola respuesta.&lt;/p&gt;

&lt;p&gt;Para hacer eso, podemos usar el operador &lt;code&gt;forkJoin&lt;/code&gt; de RxJS, que es similar al antiguo &lt;code&gt;$q.all()&lt;/code&gt; de Angular 1 y te permite ejecutar dos o más Observables en paralelo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;getAuthorWithBooks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;forkJoin&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/authors/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/authors/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/books&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Will return:

{
  id: 1,
  first_name: 'Adrián',
  last_name: 'UB'
  books: [{
    id: 10,
    title: 'Awesome book',
    author_id: 1
  },
  ...
  ]
}

*/&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Como puede ver en el ejemplo, &lt;code&gt;forkJoin&lt;/code&gt; devuelve una matriz con los resultados de los Observables unidos. Podemos componerlos como necesitemos, para devolver solo un objeto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combinando Observables en serie
&lt;/h2&gt;

&lt;p&gt;¿Qué pasa si necesitamos, por ejemplo, obtener la información del autor de un libro? Deberíamos obtener los datos del libro primero y, solo cuando los obtengamos, podemos llamar al punto final del autor con la identificación del autor.&lt;/p&gt;

&lt;p&gt;En este caso, tendremos que usar el operador &lt;code&gt;switchMap&lt;/code&gt; de RxJS, que es similar al operador &lt;code&gt;map&lt;/code&gt; de RxJS habitual. La diferencia es que le permite encadenar dos Observables, devolviendo un nuevo Observable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;getBookAuthor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/books/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;switchMap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;book&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/authors/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Will return:

{
  id: 1,
  first_name: 'Adrián',
  last_name: 'UB'
}

*/&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;En este caso, lo que obtendremos es solo la información del autor. ¿Y si queremos también el objeto libro? Como antes, tenemos que componer nuestros objetos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;getBookWithAuthor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/books/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;switchMap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;book&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/authors/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Will return:

{
  id: 10,
  title: 'Awesome book',
  author_id: 1
  author: {
    id: 1,
    first_name: 'Adrián',
    last_name: 'UB'
  }
}

*/&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Combinando Observables en serie y en paralelo
&lt;/h2&gt;

&lt;p&gt;¿Qué pasa si ahora quisiéramos hacer lo mismo (obtener el libro con su autor), pero para varios libros a la vez? Podemos combinar &lt;code&gt;forkJoin&lt;/code&gt; y &lt;code&gt;switchMap&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;getBooksWithAuthor&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/books/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;switchMap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;forkJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;book&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/authors/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
              &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Will return:

[{
  id: 10,
  title: 'Awesome book',
  author_id: 1
  author: {
    id: 1,
    first_name: 'Adrián',
    last_name: 'UB'
  }
},
{
  id: 11,
  title: 'Another awesome book',
  author_id: 2
  author: {
    id: 2,
    first_name: 'Linneth',
    last_name: 'BS'
  }
}]

*/&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Parece complicado, pero es bastante fácil: después de obtener la lista de libros, usamos el &lt;code&gt;switchMap&lt;/code&gt;, para fusionar la llamada anterior con el resultado de &lt;code&gt;forkJoin&lt;/code&gt;, que se llama solo si tenemos algunos libros, de lo contrario solo devolvemos un Observable que contiene una matriz vacía.&lt;/p&gt;

&lt;p&gt;Quizás se esté preguntando por qué estamos usando &lt;code&gt;forkJoin&lt;/code&gt; aquí, ya que solo hay una llamada. Pero, si se ve mejor, habrá tantas llamadas como libros recibamos. De hecho, estamos haciendo un bucle en la matriz de libros con la función &lt;code&gt;Array.map&lt;/code&gt;, que no es lo mismo que el operador &lt;code&gt;map&lt;/code&gt; de RxJS.&lt;/p&gt;

&lt;p&gt;Luego, por la llamada de cada autor, combinamos nuestros objetos y devolvemos el libro, que es lo que queremos. ¡Fácil!&lt;/p&gt;

&lt;p&gt;Otro ejemplo puede ser obtener información sobre el autor y el editor de un solo libro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;getBookWithDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/books/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;switchMap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;book&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;forkJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/authors/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author_id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/editors/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;editor_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
          &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
          &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
          &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Will return:

{
  id: 10,
  title: 'Awesome book',
  author_id: 1,
  editor_id: 42
  author: {
    id: 1,
    first_name: 'Adrián',
    last_name: 'UB'
  },
  editor: {
    id: 42,
    name: 'Universe Editor'
  }
}

*/&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Como podemos ver, &lt;code&gt;forkJoin&lt;/code&gt; devuelve una matriz con el resultado de cada Observable, que podemos componer para devolver el objeto final. Nótese que estamos uniendo el propio objeto libro, convirtiéndolo en un Observable gracias al operador &lt;code&gt;of&lt;/code&gt; RxJS, para que podamos acceder a él en el siguiente &lt;code&gt;map&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¡Espero que el operador RxJS sea más claro ahora! ¡Disfrutar!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>rxjs</category>
    </item>
    <item>
      <title>How to use Simple Icons on Laravel Blade</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Sun, 11 Apr 2021 17:55:25 +0000</pubDate>
      <link>https://dev.to/ub/how-to-use-simple-icons-on-laravel-blade-2155</link>
      <guid>https://dev.to/ub/how-to-use-simple-icons-on-laravel-blade-2155</guid>
      <description>&lt;h1&gt;
  
  
  Blade Simple Icons
&lt;/h1&gt;

&lt;p&gt;A package to easily make use of &lt;a href="https://simpleicons.org/" rel="noopener noreferrer"&gt;Simple Icons&lt;/a&gt; in your Laravel Blade views.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PHP 7.4 or higher&lt;/li&gt;
&lt;li&gt;Laravel 8.0 or higher&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;You can install the package via composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require ublabs/blade-simple-icons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Icons can be used as self-closing Blade components which will be compiled to SVG icons:&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;x-simpleicon-laravel /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can also pass classes to your icon components:&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;x-simpleicon-laravel class="w-6 h-6 text-red-500"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And even use inline styles:&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;x-simpleicon-laravel style="color: #FF2D20"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Raw SVG Icons
&lt;/h3&gt;

&lt;p&gt;If you want to use the raw SVG icons as assets, you can publish them using:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;blade-simple-icons &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then use them in your views like:&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;img src="{{ asset('vendor/blade-simple-icons/laravel.svg') }}" width="10" height="10"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ublabs" rel="noopener noreferrer"&gt;
        ublabs
      &lt;/a&gt; / &lt;a href="https://github.com/ublabs/blade-simple-icons" rel="noopener noreferrer"&gt;
        blade-simple-icons
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A package to easily make use of Simple Icons in your Laravel Blade views.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;
    Blade Simple Icons
&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;
    &lt;a href="https://github.com/ublabs/blade-simple-icons/actions?query=workflow%3ATests" rel="noopener noreferrer"&gt;
        &lt;img src="https://github.com/ublabs/blade-simple-icons/workflows/Tests/badge.svg" alt="Tests"&gt;
    &lt;/a&gt;
    &lt;a href="https://packagist.org/packages/ublabs/blade-simple-icons" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/e038f0bf968a4def065f9d1efaaffa21c39b41a494901b7ce67551669f54d56f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f75626c6162732f626c6164652d73696d706c652d69636f6e73" alt="Latest Stable Version"&gt;
    &lt;/a&gt;
    &lt;a href="https://packagist.org/packages/ublabs/blade-simple-icons" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/9e259fa83c6a04949b52b526bb6e1e029b654f111477fa4e32f889e98cf4ac35/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f75626c6162732f626c6164652d73696d706c652d69636f6e73" alt="Total Downloads"&gt;
    &lt;/a&gt;
&lt;/p&gt;




&lt;p&gt;A package to easily make use of &lt;a href="https://simpleicons.org/" rel="nofollow noopener noreferrer"&gt;Simple Icons&lt;/a&gt; in your Laravel Blade views.&lt;/p&gt;

&lt;p&gt;For a full list of available icons see the &lt;a href="https://github.com/ublabs/blade-simple-icons./resources/svg" rel="noopener noreferrer"&gt;SVG directory&lt;/a&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Requirements&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;PHP 7.4 or higher&lt;/li&gt;
&lt;li&gt;Laravel 8.0 or higher&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;You can install the package via composer:&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;composer require ublabs/blade-simple-icons&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Icons can be used as self-closing Blade components which will be compiled to SVG icons:&lt;/p&gt;

&lt;div class="highlight highlight-text-html-php-blade notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&amp;lt;&lt;span class="pl-ent"&gt;x-simpleicon-laravel&lt;/span&gt; /&amp;gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can also pass classes to your icon components:&lt;/p&gt;

&lt;div class="highlight highlight-text-html-php-blade notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&amp;lt;&lt;span class="pl-ent"&gt;x-simpleicon-laravel&lt;/span&gt; &lt;span class="pl-e"&gt;class&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;w-6 h-6 text-red-500&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;/&amp;gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And even use inline styles:&lt;/p&gt;

&lt;div class="highlight highlight-text-html-php-blade notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&amp;lt;&lt;span class="pl-ent"&gt;x-simpleicon-laravel&lt;/span&gt; &lt;span class="pl-e"&gt;style&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;&lt;span class="pl-c1"&gt;color&lt;/span&gt;&lt;/span&gt;: &lt;span class="pl-c1"&gt;#FF2D20&lt;/span&gt;&lt;/span&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;/&amp;gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Raw SVG Icons&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;If you want to use the raw SVG icons as assets, you can publish them using:&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;php artisan vendor:publish --tag=blade-simple-icons --force&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then use them in your views like:&lt;/p&gt;

&lt;div class="highlight highlight-text-html-php-blade notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&amp;lt;&lt;span class="pl-ent"&gt;img&lt;/span&gt; &lt;span class="pl-e"&gt;src&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;span class="pl-c1"&gt;{{&lt;/span&gt;&lt;span class="pl-s1"&gt; &lt;span class="pl-en"&gt;asset&lt;/span&gt;(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;vendor/blade-simple-icons/laravel.svg&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;) &lt;/span&gt;&lt;span class="pl-c1"&gt;&lt;span class="pl-s1"&gt;}&lt;/span&gt;}&lt;/span&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-e"&gt;width&lt;/span&gt;=&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ublabs/blade-simple-icons" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>laravel</category>
      <category>svg</category>
      <category>blade</category>
    </item>
    <item>
      <title>How to use Netlify CMS on Vercel</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Fri, 12 Feb 2021 18:58:27 +0000</pubDate>
      <link>https://dev.to/adrianub/how-to-use-netlify-cms-on-vercel-1l0o</link>
      <guid>https://dev.to/adrianub/how-to-use-netlify-cms-on-vercel-1l0o</guid>
      <description>&lt;p&gt;Hi everyone, today I want to introduce you to a serverless service to use &lt;a href="https://www.netlifycms.org/" rel="noopener noreferrer"&gt;Netlify CMS&lt;/a&gt; for sites hosted on &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What you need to do is modify your &lt;code&gt;config.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;github | gitlab&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;adrian-ub/adrian-ub&lt;/span&gt; &lt;span class="c1"&gt;# Path to your Github/Gitlab repository&lt;/span&gt;
  &lt;span class="na"&gt;branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt; &lt;span class="c1"&gt;# Branch to update&lt;/span&gt;
  &lt;span class="na"&gt;base_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://netlify-cms.adrianub.vercel.app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can visit: &lt;a href="https://netlify-cms.adrianub.vercel.app" rel="noopener noreferrer"&gt;https://netlify-cms.adrianub.vercel.app&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ublabs" rel="noopener noreferrer"&gt;
        ublabs
      &lt;/a&gt; / &lt;a href="https://github.com/ublabs/netlify-cms-oauth" rel="noopener noreferrer"&gt;
        netlify-cms-oauth
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Use Netlify CMS for sites hosted on Vercel.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a href="https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fublabs%2Fnetlify-cms-oauth&amp;amp;env=OAUTH_GITHUB_CLIENT_ID,OAUTH_GITHUB_CLIENT_SECRET,OAUTH_GITLAB_CLIENT_ID,OAUTH_GITLAB_CLIENT_SECRET&amp;amp;envDescription=Create%20a%20OAuth%20App%20on%20Github%20and%20Gitlab%20and%20set%20variables%20information%20&amp;amp;envLink=https%3A%2F%2Fgithub.com%2Fublabs%2Fnetlify-cms-oauth%23deploy&amp;amp;project-name=netlify-cms-oauth&amp;amp;repo-name=netlify-cms-oauth&amp;amp;demo-title=Netlify%20CMS%20OAuth&amp;amp;demo-description=Use%20Netlify%20CMS%20for%20sites%20hosted%20on%20Vercel.&amp;amp;demo-url=https%3A%2F%2Fnetlify-cms-adrianub.vercel.app" rel="nofollow noopener noreferrer"&gt;&lt;img height="100" src="https://camo.githubusercontent.com/20bea215d35a4e28f2c92ea5b657d006b087687486858a40de2922a4636301ab/68747470733a2f2f76657263656c2e636f6d2f627574746f6e" alt="Deploy with Vercel"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;
    &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;
        Netlify CMS on Vercel
    &lt;/h3&gt;
&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;p dir="auto"&amp;gt;
    A simple OAuth2 serverless gateway for Netlify CMS
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why do I need this?&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;If you would like to use Netlify CMS to manage your site deployed to Vercel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and &lt;a href="https://gitlab.com" rel="nofollow noopener noreferrer"&gt;Gitlab&lt;/a&gt; requires a server for authentication and Netlify provides this server only for sites deployed to it. Fortunately, such server is rather small and can work with Vercel's serverless functions.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;In yours projects modify &lt;code&gt;config.yml&lt;/code&gt; file:&lt;/p&gt;

&lt;div class="highlight highlight-source-yaml notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;backend&lt;/span&gt;:
  &lt;span class="pl-ent"&gt;name&lt;/span&gt;: &lt;span class="pl-s"&gt;[github | gitlab]&lt;/span&gt;
  &lt;span class="pl-ent"&gt;repo&lt;/span&gt;: &lt;span class="pl-s"&gt;adrian-ub/adrian-ub &lt;/span&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Path to your Github/Gitlab repository&lt;/span&gt;
  &lt;span class="pl-ent"&gt;branch&lt;/span&gt;: &lt;span class="pl-s"&gt;main &lt;/span&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Branch to update&lt;/span&gt;
  &lt;span class="pl-ent"&gt;base_url&lt;/span&gt;: &lt;span class="pl-s"&gt;https://netlify-cms.adrianub.vercel.app&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Deploy&lt;/h2&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Create Github OAuth App:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="https://github.com/settings/developers" rel="noopener noreferrer"&gt;developer settings&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;Authorization callback URL&lt;/code&gt; to your deployed oauth website's callback URL
&lt;code&gt;https://netlify-cms.adrianub.vercel.app/callback&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Create Gitlab OAuth app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="https://gitlab.com/-/profile/applications" rel="nofollow noopener noreferrer"&gt;User settings &amp;gt; Applications&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;Redirect URI&lt;/code&gt; to your deployed oauth website's callback URL:
&lt;code&gt;https://netlify-cms.adrianub.vercel.app/callback&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Set environment variables on &lt;code&gt;Vercel&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;OAUTH_GITHUB_CLIENT_ID=&lt;span class="pl-k"&gt;&amp;lt;&lt;/span&gt;you-client-id&lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt;
OAUTH_GITHUB_CLIENT_SECRET=&lt;span class="pl-k"&gt;&amp;lt;&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ublabs/netlify-cms-oauth" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>vercel</category>
      <category>netlify</category>
      <category>github</category>
    </item>
    <item>
      <title>Create beautiful looking social images for your Blog and Packages</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Wed, 03 Feb 2021 21:00:11 +0000</pubDate>
      <link>https://dev.to/adrianub/create-beautiful-looking-social-images-for-your-blog-and-packages-1m2k</link>
      <guid>https://dev.to/adrianub/create-beautiful-looking-social-images-for-your-blog-and-packages-1m2k</guid>
      <description>&lt;p&gt;Hi everyone, today I want to present a serverless service for image generator. &lt;a href="https://banners.adrianub.vercel.app" rel="noopener noreferrer"&gt;Social Image Generator - Adrián UB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Serverless service that generates dynamic Open Graph images that you can embed in your  tags.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is an Open Graph Image?
&lt;/h1&gt;

&lt;p&gt;Have you ever posted a hyperlink to Twitter, Facebook, or Slack and seen an image popup? How did your social network know how to "unfurl" the URL and get an image? The answer is in your &lt;/p&gt;.

&lt;p&gt;The Open Graph protocol says you can put a  tag in the &lt;/p&gt; of a webpage to define this image.

&lt;p&gt;It looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Title&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"http://example.com/logo.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Why use this service?
&lt;/h1&gt;

&lt;p&gt;The short answer is that it would take a long time to painstakingly design an image for every single blog post and every single documentation page. And we don't want the exact same image for every blog post because that wouldn't make the article stand out when it was shared to Twitter.&lt;/p&gt;

&lt;p&gt;That's where banners.adrianub.vercel.app comes in. We can simply pass the title of our blog post to our generator service and it will generate the image for us on the fly!&lt;/p&gt;

&lt;p&gt;It looks like 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;head&amp;gt;
  &amp;lt;title&amp;gt;Hello World&amp;lt;/title&amp;gt;
  &amp;lt;meta property="og:image" content="https://banners.adrianub.vercel.app/Hello%20World.png" /&amp;gt;
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbanners.adrianub.vercel.app%2FHello%2520World.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%2Fbanners.adrianub.vercel.app%2FHello%2520World.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now try changing the text &lt;code&gt;Hello%20World&lt;/code&gt; to the title of your choosing and watch the magic happen ✨&lt;/p&gt;

&lt;p&gt;This service also lets you generate beautiful looking social images for your PHP, Laravel packages, NPM and Yarn. You have already put a lot of time and effort into your package, so why not make it look beautiful using this service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbanners.adrianub.vercel.app%2FMy%2520Package.png%3Ftype%3Dpackage%26theme%3Dlight%26packageManager%3Dyarn%2Badd%26packageName%3D%2540org%252Fmy-awesome-package%26description%3DThis%2Bis%2Bwhy%2Bit%2527s%2Bawesome%26images%3Dangular%26widths%3D250%26heights%3D250%26images%3Dtailwindcss%26widths%3D250%26heights%3D250%26pattern%3Darchitect%26md%3D1%26showWatermark%3D1%26fontSize%3D100px" 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%2Fbanners.adrianub.vercel.app%2FMy%2520Package.png%3Ftype%3Dpackage%26theme%3Dlight%26packageManager%3Dyarn%2Badd%26packageName%3D%2540org%252Fmy-awesome-package%26description%3DThis%2Bis%2Bwhy%2Bit%2527s%2Bawesome%26images%3Dangular%26widths%3D250%26heights%3D250%26images%3Dtailwindcss%26widths%3D250%26heights%3D250%26pattern%3Darchitect%26md%3D1%26showWatermark%3D1%26fontSize%3D100px"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  My repository
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/adrian-ub" rel="noopener noreferrer"&gt;
        adrian-ub
      &lt;/a&gt; / &lt;a href="https://github.com/adrian-ub/package-banners" rel="noopener noreferrer"&gt;
        package-banners
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Create beautiful looking social images for your Blog and Packages.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a href="https://vercel.com/new/project?template=adrian-ub/banners" rel="nofollow noopener noreferrer"&gt;&lt;img width="128" src="https://camo.githubusercontent.com/20bea215d35a4e28f2c92ea5b657d006b087687486858a40de2922a4636301ab/68747470733a2f2f76657263656c2e636f6d2f627574746f6e"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;&lt;a href="https://banners.adrianub.vercel.app" rel="nofollow noopener noreferrer"&gt;Open Graph Image as a Service&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/1b357042bb4e15090974bdfca8fb4140c7839b4a72e11ccf6136c36523aaac66/68747470733a2f2f62616e6e6572732e61647269616e75622e76657263656c2e6170702f4d616b65253230796f757225323042616e6e657273253230616e642532304f70656e253230536f757263652532307061636b616765732532307368696e652c253230627925323067656e65726174696e6725323062656175746966756c253230736f6369616c253230696d616765732e2e706e673f7468656d653d6c69676874266d643d31267061747465726e3d61726368697465637426617574686f723d416472692543332541316e2b554226757365726e616d653d61647269616e2d7562"&gt;&lt;img src="https://camo.githubusercontent.com/1b357042bb4e15090974bdfca8fb4140c7839b4a72e11ccf6136c36523aaac66/68747470733a2f2f62616e6e6572732e61647269616e75622e76657263656c2e6170702f4d616b65253230796f757225323042616e6e657273253230616e642532304f70656e253230536f757263652532307061636b616765732532307368696e652c253230627925323067656e65726174696e6725323062656175746966756c253230736f6369616c253230696d616765732e2e706e673f7468656d653d6c69676874266d643d31267061747465726e3d61726368697465637426617574686f723d416472692543332541316e2b554226757365726e616d653d61647269616e2d7562" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Serverless service that generates dynamic Open Graph images that you can embed in your &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;

&lt;p&gt;For each keystroke, headless chromium is used to render an HTML page and take a screenshot of the result which gets cached.&lt;/p&gt;

&lt;p&gt;See the image embedded in the tweet for a real use case.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What is an Open Graph Image?&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Have you ever posted a hyperlink to Twitter, Facebook, or Slack and seen an image popup
How did your social network know how to "unfurl" the URL and get an image?
The answer is in your &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://ogp.me" rel="nofollow noopener noreferrer"&gt;Open Graph protocol&lt;/a&gt; says you can put a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of a webpage to define this image.&lt;/p&gt;
&lt;p&gt;It looks like the following:&lt;/p&gt;
&lt;div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;head&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;title&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;Title&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-ent"&gt;title&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;meta&lt;/span&gt; &lt;span class="pl-c1"&gt;property&lt;/span&gt;="&lt;span class="pl-s"&gt;og:image&lt;/span&gt;" &lt;span class="pl-c1"&gt;content&lt;/span&gt;="&lt;span class="pl-s"&gt;http://example.com/logo.jpg&lt;/span&gt;" /&amp;gt;
&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-ent"&gt;head&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/adrian-ub/package-banners" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>cover</category>
      <category>banners</category>
      <category>angular</category>
      <category>github</category>
    </item>
    <item>
      <title>Cómo usar TailwindCSS v2 con Laravel 8</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Tue, 12 Jan 2021 02:38:49 +0000</pubDate>
      <link>https://dev.to/adrianub/usar-tailwindcss-v2-con-laravel-8-4l1o</link>
      <guid>https://dev.to/adrianub/usar-tailwindcss-v2-con-laravel-8-4l1o</guid>
      <description>&lt;p&gt;Hola desarrolladores, vamos a ver cómo configurar de manera manual un entorno de desarrollo con Laravel 8 y TailwindCSS 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crear un nuevo proyecto
&lt;/h2&gt;

&lt;p&gt;Siguiendo la documentación de laravel crearemos un nuevo proyecto con &lt;code&gt;composer&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer create-project laravel/laravel laravel-tailwind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Instalar dependencias
&lt;/h2&gt;

&lt;p&gt;Luego de crear nuestro proyecto seguiremos a instalar nuestras dependencias para el desarrollo a través de &lt;code&gt;npm&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D tailwindcss autoprefixer postcss sass sass-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;o si está usando &lt;code&gt;yarn&lt;/code&gt; cómo administrador de paquetes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add -D tailwindcss autoprefixer postcss sass sass-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al momento de escribir este artículo las versiones instaladas en las dependencias son las siguientes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;devDependencies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;autoprefixer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^10.2.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;laravel-mix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^6.0.6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postcss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^8.2.4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sass&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^1.32.2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sass-loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^8.0.2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tailwindcss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^2.0.2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Crea tu archivo de configuración
&lt;/h2&gt;

&lt;p&gt;A continuación, genera tu archivo &lt;code&gt;tailwind.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx tailwindcss init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto creará un archivo &lt;code&gt;tailwind.config.js&lt;/code&gt; mínimo en la raíz de su proyecto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tailwind.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or 'media' or 'class'&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configuremos Tailwind para eliminar los estilos no utilizados en producción:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt; tailwind.config.js
&lt;span class="gd"&gt;- module.exports = {
&lt;/span&gt;&lt;span class="gi"&gt;+ module.exports = (isProd) =&amp;gt; ({
&lt;/span&gt;&lt;span class="gd"&gt;-  purge: [],
&lt;/span&gt;&lt;span class="gi"&gt;+  purge: {
+    enabled: isProd,
+    content: [
+       "./app/**/*.php",
+       "./resources/**/*.html",
+       "./resources/**/*.php",
+     ],
+  },
&lt;/span&gt;  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
&lt;span class="gd"&gt;- }
&lt;/span&gt;&lt;span class="gi"&gt;+ })
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuración para AlpineJs
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt; tailwind.config.js
&lt;span class="gd"&gt;- module.exports = {
&lt;/span&gt;&lt;span class="gi"&gt;+ module.exports = (isProd) =&amp;gt; ({
&lt;/span&gt;&lt;span class="gd"&gt;-  purge: [],
&lt;/span&gt;&lt;span class="gi"&gt;+  purge: {
+    enabled: isProd,
+    content: [
+       "./app/**/*.php",
+       "./resources/**/*.html",
+       "./resources/**/*.php",
+     ],
+     options: {
+            defaultExtractor: (content) =&amp;gt;
+                content.match(/[\w-/.:]+(?&amp;lt;!:)/g) || [],
+            whitelistPatterns: [/-active$/, /-enter$/, /-leave-to$/, /show$/],
+        },
+  },
&lt;/span&gt;  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
&lt;span class="gd"&gt;- }
&lt;/span&gt;&lt;span class="gi"&gt;+ })
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Crear archivo SCSS
&lt;/h2&gt;

&lt;p&gt;Vamos a la ruta &lt;code&gt;resources/sass&lt;/code&gt;y creamos un archivo llamado &lt;code&gt;app.scss&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="nt"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="nt"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="nt"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configurar Tailwind con Laravel Mix
&lt;/h2&gt;

&lt;p&gt;En su &lt;code&gt;webpack.mix.js&lt;/code&gt;, agregue &lt;code&gt;tailwindcss&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;laravel-mix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tailwindcss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tailwindcss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isProd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inProduction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tailwindConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./tailwind.config&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;isProd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;mix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resources/js/app.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public/js/app.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resources/sass/app.scss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public/css/app.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;processCssUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;postCss&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tailwindcss&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tailwindConfig&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceMaps&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isProd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora solo falta correr el comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Desarrollo
npm run development

// Producción
npm run production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agregar los estilos a tu aplicación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{{ url(mix('css/app.css')) }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y comenzar a probar con TailwindCSS.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Cómo usar Tailwind CSS 2 en Angular 11 🎉🎉</title>
      <dc:creator>Adrián UB</dc:creator>
      <pubDate>Tue, 15 Dec 2020 01:38:07 +0000</pubDate>
      <link>https://dev.to/adrianub/como-usar-tailwind-css-en-angular-11-1j8f</link>
      <guid>https://dev.to/adrianub/como-usar-tailwind-css-en-angular-11-1j8f</guid>
      <description>&lt;p&gt;Tailwind CSS es un marco CSS de utilidad que facilita la creación de sistemas de diseño excepcionales. Se basa en la filosofía de que prácticamente cualquier cosa que pueda hacer con CSS, puede lograrlo directamente agregando un montón de clases de utilidad directamente en su HTML. Angular, por otro lado, es una plataforma que le permite crear aplicaciones empresariales de alta calidad. Combine Angular con Tailwind CSS y tendrá una pila perfecta para crear aplicaciones web de primer nivel.&lt;/p&gt;

&lt;p&gt;Tailwind es un complemento de PostCSS, pero desafortunadamente, la CLI de Angular, aunque usa PostCSS bajo el capó para algunas operaciones, no es compatible con los complementos de PostCSS a partir de hoy. Entonces, agregar Tailwind a su aplicación Angular no es tan fácil cómo debería ser.&lt;/p&gt;

&lt;p&gt;En este artículo, lo guiaré a través de cómo puede eludir esta limitación y agregar Tailwind CSS a su aplicación Angular.&lt;/p&gt;

&lt;h1&gt;
  
  
  Crear un nuevo proyecto
&lt;/h1&gt;

&lt;p&gt;Versión de angular al crear esta publicación&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 11.0.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Comando para crear un nuevo proyecto&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng new angular11-tailwindcss --style=scss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Instalar dependencias
&lt;/h1&gt;

&lt;p&gt;Prosigamos instalando las dependencias requeridas a través de npm:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D tailwindcss autoprefixer postcss postcss-scss postcss-import postcss-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;o si está usando Yarn cómo administrador de paquetes:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add -D tailwindcss autoprefixer postcss postcss-scss postcss-import postcss-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ahora necesitamos un paquete para poder crear nuestro &lt;code&gt;webpack.config.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nuestro paquete es &lt;code&gt;ngx-build-plus&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng add ngx-build-plus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Configurar Tailwind CSS
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Iniciamos el archivo de configuración &lt;code&gt;tailwind.config.js&lt;/code&gt; en el proyecto, usando el siguiente comando &lt;code&gt;npx tailwind init&lt;/code&gt; y tendremos cómo resultado este código
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or 'media' or 'class'&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;En el archivo &lt;code&gt;styles.scss&lt;/code&gt; añadimos las siguientes líneas
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'tailwindcss/base'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'tailwindcss/components'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'tailwindcss/utilities'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Configurar Webpack
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Creamos un archivo llamado &lt;code&gt;webpack.config.js&lt;/code&gt; en la raíz de nuestro proyecto y agregamos las siguientes líneas
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;scss$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postcss-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;postcssOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postcss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;syntax&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postcss-scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postcss-import&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tailwindcss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;autoprefixer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Por último modificaremos nuestro archivo &lt;code&gt;angular.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;{&lt;/span&gt;
    ...
    "projects": {
        "angular11-tailwindcss": {
            ...
            "architect": {
                "build": {
                    "builder": "ngx-build-plus:browser",
                    "options": {
&lt;span class="gi"&gt;+                        "extraWebpackConfig": "webpack.config.js",
&lt;/span&gt;                        ...
                    },
                    ...
                },
                "serve": {
                    "builder": "ngx-build-plus:dev-server",
                    "options": {
&lt;span class="gi"&gt;+                        "extraWebpackConfig": "webpack.config.js",
&lt;/span&gt;                        ...
                    },
                    ...
                }
            }
        }
    }
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ahora podemos correr nuestro comando &lt;code&gt;ng serve&lt;/code&gt; y probar nuestra aplicación &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kPHMh-hV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j7e9ltyskxr1sxwcrhp7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kPHMh-hV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j7e9ltyskxr1sxwcrhp7.png" alt="Ng Serve output console" width="880" height="477"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  TailwindCSS
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Cómo ejemplo agregaremos el código que se encuentra en &lt;a href="https://play.tailwindcss.com/"&gt;Tailwind Pay&lt;/a&gt; en nuestro archivo &lt;code&gt;src/app/app.component.html&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"min-h-screen bg-gray-100 py-6 flex flex-col justify-center sm:py-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative py-3 sm:max-w-xl sm:mx-auto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute inset-0 bg-gradient-to-r from-cyan-400 to-light-blue-500 shadow-lg transform -skew-y-6 sm:skew-y-0 sm:-rotate-6 sm:rounded-3xl"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative px-4 py-10 bg-white shadow-lg sm:rounded-3xl sm:p-20"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"max-w-md mx-auto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/img/logo.svg"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-7 sm:h-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"divide-y divide-gray-200"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"py-8 text-base leading-6 space-y-4 text-gray-700 sm:text-lg sm:leading-7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;An advanced online playground for Tailwind CSS, including support for things like:&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"list-disc space-y-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-start"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-6 flex items-center sm:h-7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-shrink-0 h-5 w-5 text-cyan-500"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 20 20"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;fill-rule=&lt;/span&gt;&lt;span class="s"&gt;"evenodd"&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"&lt;/span&gt; &lt;span class="na"&gt;clip-rule=&lt;/span&gt;&lt;span class="s"&gt;"evenodd"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ml-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                  Customizing your
                  &lt;span class="nt"&gt;&amp;lt;code&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-sm font-bold text-gray-900"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;tailwind.config.js&lt;span class="nt"&gt;&amp;lt;/code&amp;gt;&lt;/span&gt; file
                &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-start"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-6 flex items-center sm:h-7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-shrink-0 h-5 w-5 text-cyan-500"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 20 20"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;fill-rule=&lt;/span&gt;&lt;span class="s"&gt;"evenodd"&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"&lt;/span&gt; &lt;span class="na"&gt;clip-rule=&lt;/span&gt;&lt;span class="s"&gt;"evenodd"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ml-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                  Extracting classes with
                  &lt;span class="nt"&gt;&amp;lt;code&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-sm font-bold text-gray-900"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;@apply&lt;span class="nt"&gt;&amp;lt;/code&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-start"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-6 flex items-center sm:h-7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-shrink-0 h-5 w-5 text-cyan-500"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 20 20"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;fill-rule=&lt;/span&gt;&lt;span class="s"&gt;"evenodd"&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"&lt;/span&gt; &lt;span class="na"&gt;clip-rule=&lt;/span&gt;&lt;span class="s"&gt;"evenodd"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ml-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Code completion with instant preview&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Perfect for learning how the framework works, prototyping a new idea, or creating a demo to share online.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pt-6 text-base leading-6 font-bold sm:text-lg sm:leading-7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Want to dig deeper into Tailwind?&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://tailwindcss.com/docs"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-cyan-600 hover:text-cyan-700"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; Read the docs &lt;span class="ni"&gt;&amp;amp;rarr;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_gKQSMn5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/codn7irmv4i8p93ytjyp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_gKQSMn5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/codn7irmv4i8p93ytjyp.png" alt="Alt Text" width="880" height="470"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Repositorio con un ejemplo
&lt;/h1&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/adrian-ub"&gt;
        adrian-ub
      &lt;/a&gt; / &lt;a href="https://github.com/adrian-ub/angular11-tailwindcss"&gt;
        angular11-tailwindcss
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Angular 11 TailwindCSS 2&lt;/h1&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/adrian-ub/angular11-tailwindcss/blob/main/image.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3oTuT4LS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/adrian-ub/angular11-tailwindcss/raw/main/image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/adrian-ub/angular11-tailwindcss"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



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