<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Rubén Peregrina Fron-end Software Engineer Angular TypeScript Wen development React JavaScript SSR Next.js]]></title><description><![CDATA[Front-end Software Engineer using Angular, TypeScript, JavaScript , React, Next.js, web development, Flutter, SSR, web components, RxJs, NgRX]]></description><link>https://rubenperegrina.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1708544738384/OGnM-DiMa.png</url><title>Rubén Peregrina Fron-end Software Engineer Angular TypeScript Wen development React JavaScript SSR Next.js</title><link>https://rubenperegrina.com</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 19 May 2026 03:34:39 GMT</lastBuildDate><atom:link href="https://rubenperegrina.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Understanding the new Angular @let syntax]]></title><description><![CDATA[The Angular community has been asking for this feature for many years. Angular has now extended the built-in template syntax with a new way to define variables directly within the template, allowing developers to create and use variables inside the H...]]></description><link>https://rubenperegrina.com/understanding-the-new-angular-let-syntax</link><guid isPermaLink="true">https://rubenperegrina.com/understanding-the-new-angular-let-syntax</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Mon, 02 Sep 2024 14:20:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/dbOV1qSiL-c/upload/24705aca31ebda01ffaf9fa86a46a5bf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The Angular community has been asking for this feature for many years. Angular has now extended the built-in template syntax with a new way to define variables directly within the template, allowing developers to create and use variables inside the HTML.</p>
<p>Angular's template syntax has always supported complex operations, making development easier. However, it has been limited in certain aspects, particularly when it comes to reusing expressions across the template. Developers have often resorted to using directives or other workarounds to overcome these limitations. Now, with the introduction of <code>@let</code>, we have a native solution that simplifies this process.</p>
<h2 id="heading-introducing-the-let-syntax">Introducing the let syntax</h2>
<p>The <code>@let</code> syntax allows you to define variables directly in the template and reuse them throughout. This new feature provides a more ergonomic and straightforward way to handle variables in your templates. Let's take a look at a basic example:</p>
<pre><code class="lang-xml">@let name = 'Rubén';
<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Dashboard for {{name}}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
Hello, {{name}}
</code></pre>
<p>In this example, the variable <code>name</code> is defined and used seamlessly within the template. This can be especially powerful in more complex templates where you need to reuse values derived from expressions.</p>
<h3 id="heading-practical-examples-and-use-cases">Practical examples and use cases</h3>
<p>Here are a few more examples of how <code>@let</code> can be used in your Angular templates:</p>
<ol>
<li><p><strong>Using with a template variable referencing an element:</strong></p>
<pre><code class="lang-xml"> <span class="hljs-tag">&lt;<span class="hljs-name">input</span> #<span class="hljs-attr">name</span>&gt;</span>
 @let greeting = 'Hello ' + name.value;
 <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{greeting}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
</li>
<li><p><strong>Using with an async pipe:</strong></p>
<pre><code class="lang-xml"> @let user = user$ | async;
 <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Welcome, {{user.name}}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
</code></pre>
</li>
</ol>
<p>These examples demonstrate how <code>@let</code> can streamline your templates by reducing redundancy and improving readability.</p>
<h3 id="heading-scope-and-limitations">Scope and limitations</h3>
<p>When using <code>@let</code>, it's important to remember that these variables are scoped to the current view and its descendants. This means that they cannot be accessed by parent or sibling views. For example:</p>
<pre><code class="lang-xml">@let topLevel = value;

@if (condition) {
  @let nested = value;
}

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> *<span class="hljs-attr">ngIf</span>=<span class="hljs-string">"condition"</span>&gt;</span>
  @let nestedNgIf = value;
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Valid --&gt;</span>
{{topLevel}}

<span class="hljs-comment">&lt;!-- Error: Not accessible outside @if or *ngIf scopes --&gt;</span>
{{nested}}
{{nestedNgIf}}
</code></pre>
<p>Additionally, <code>@let</code> declarations are read-only and cannot be reassigned. Their values will be recomputed on each change detection, such as when an async pipe's value changes. Attempting to reassign them will result in a type-checking error.</p>
<pre><code class="lang-xml">@let value = 10;
<span class="hljs-comment">&lt;!-- Error: `value` is not assignable --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"value = value + 1"</span>&gt;</span>Change the value<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<h3 id="heading-syntax-definition">Syntax Definition</h3>
<p>Let's break down the syntax for <code>@let</code>:</p>
<ol>
<li><p>The <code>@let</code> keyword.</p>
</li>
<li><p>Followed by one or more whitespaces (no new lines allowed).</p>
</li>
<li><p>Followed by a valid JavaScript name and optional whitespaces.</p>
</li>
<li><p>Followed by the equals (<code>=</code>) symbol and optional whitespaces.</p>
</li>
<li><p>Followed by an Angular expression, which can span multiple lines.</p>
</li>
<li><p>Terminated by the semicolon (<code>;</code>) symbol.</p>
</li>
</ol>
<h3 id="heading-conclusion">Conclusion</h3>
<p>The introduction of <code>@let</code> in Angular represents a significant enhancement in the way developers can manage variables within templates. This feature not only improves code readability but also provides a more intuitive and efficient method of working with template variables. As Angular continues to evolve, features like <code>@let</code> demonstrate the framework's commitment to optimising the developer experience.</p>
]]></content:encoded></item><item><title><![CDATA[Goodbye Zone.js: What's new in Angular 18?]]></title><description><![CDATA[Angular 18 is revolutionizing the way change detection is handled, removing the dependency on Zone.js. This change began in Angular 17 with the introduction of Signals. Now, instead of depending only on Signal components, the new hybrid detection sys...]]></description><link>https://rubenperegrina.com/goodbye-zonejs-whats-new-in-angular-18</link><guid isPermaLink="true">https://rubenperegrina.com/goodbye-zonejs-whats-new-in-angular-18</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular 2]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[web]]></category><category><![CDATA[signals]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Wed, 17 Jul 2024 16:31:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/3YAIvBNlZM4/upload/66567b96945a70129a48ac7856ca33d2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Angular 18</strong> is revolutionizing the way change detection is handled, removing the dependency on <strong>Zone.js</strong>. This change began in Angular 17 with the introduction of <strong>Signals</strong>. Now, instead of depending only on Signal components, the new hybrid detection system will automatically trigger change detection for any invoker of <code>markForCheck</code>, whether they are inside or outside of Zone.js.</p>
<h3 id="heading-what-is-zonejs">What is Zone.js?</h3>
<p><strong>Zone.js</strong> acts as a helper to check whether each component in a large application needs to be updated. Each time you use a component, <strong>Zone.js</strong> ensures that any change is correctly detected and updated.</p>
<h3 id="heading-signals-the-introduction-in-angular-17">Signals: The introduction in Angular 17</h3>
<p><strong>Angular 17</strong> introduced a new concept called signals. Signals allow for more efficient interactions with components, reducing the dependency on Zone.js. Signals allow developers to handle state changes more explicitly.</p>
<h3 id="heading-the-revolution-of-angular-18-hybrid-system">The revolution of Angular 18: Hybrid system</h3>
<p><strong>Angular 18</strong> takes this a step further with a <strong>hybrid change detection system</strong>. Now, any invoker of <code>markForCheck</code> will automatically trigger change detection, regardless of whether it is inside or outside of Zone.js.</p>
<p>Here is an example to illustrate this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component, ChangeDetectorRef, ChangeDetectionStrategy } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-my-component'</span>,
  template: <span class="hljs-string">`&lt;div&gt;{{ mySignal }}&lt;/div&gt;`</span>,
  changeDetection: ChangeDetectionStrategy.OnPush
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> MyComponent {
  mySignal = <span class="hljs-string">'Initial Value'</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> cdr: ChangeDetectorRef</span>) {}

  ngOnInit() {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">this</span>.mySignal = <span class="hljs-string">'Updated Value'</span>;
      <span class="hljs-built_in">this</span>.cdr.markForCheck();
    }, <span class="hljs-number">3000</span>);
  }
}
</code></pre>
<p>In this example, we manually inject <code>ChangeDetectorRef</code> and invoke <code>markForCheck</code> after updating the component's state.</p>
<h3 id="heading-using-signals-for-simplicity">Using Signals for simplicity</h3>
<p>With the new Signals feature in <strong>Angular 18</strong>, you can simplify this process:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component, ChangeDetectionStrategy } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-my-component'</span>,
  template: <span class="hljs-string">`{{ mySignal() }}`</span>,
  changeDetection: ChangeDetectionStrategy.OnPush
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> MyComponent {
  mySignal = signal(<span class="hljs-number">0</span>);

  ngOnInit() {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">this</span>.mySignal.set(<span class="hljs-number">1</span>), <span class="hljs-number">3000</span>);
  }
}
</code></pre>
<p>In this improved version, we use a signal, and the view updates automatically without needing to manually call <code>markForCheck</code>.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>The main benefit of this new system is the <strong>reduction in dependency on Zone.js</strong>, which can improve <strong>performance and code clarity</strong>. However, it is important for developers to understand how Signals and the hybrid system work in order to make the most of these improvements. <strong>Angular 18 is a revolution in change detection</strong>, making applications more efficient and easier to maintain. Removing the dependency on Zone.js, along with the introduction of Signals and the hybrid system, is a significant step forward for Angular developers.</p>
]]></content:encoded></item><item><title><![CDATA[Generate documentation for your Angular application with Compodoc]]></title><description><![CDATA[One of the tasks that every developer hates is documenting. We know that it is very important and could be helpful in the future, but it's a tedious task.
Documentation is another part of development, the same as taking the recruitment, development, ...]]></description><link>https://rubenperegrina.com/generate-documentation-for-your-angular-application-with-compodoc</link><guid isPermaLink="true">https://rubenperegrina.com/generate-documentation-for-your-angular-application-with-compodoc</guid><category><![CDATA[compodoc]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular 2]]></category><category><![CDATA[webdev]]></category><category><![CDATA[webdevelopment]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[documentation]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Mon, 17 Jun 2024 17:37:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Y7d265_7i08/upload/11ad14e6a31ae8e941c631b442d3fdb4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the tasks that every developer hates is documenting. We know that it is very important and could be helpful in the future, but it's a tedious task.</p>
<p>Documentation is another part of development, the same as taking the recruitment, development, QA, etc. Documenting our application <strong>helps with onboarding new teammates, fixing future issues and better understanding the project</strong>. In this article, we will learn about what Compodoc is, its main features, how to set it up and more.</p>
<h2 id="heading-what-is-compodoc">What is Compodoc?</h2>
<p>Compodoc is a documentation tool for Angular applications. <strong>It generates static documentation of your application automatically</strong>. Once it is configured, you don't have to do anything more.</p>
<p>Compodoc has support for <a target="_blank" href="https://angular.io/"><strong>Angular</strong></a>, <a target="_blank" href="https://nestjs.com/"><strong>NestJS</strong></a>, and <a target="_blank" href="https://stenciljs.com/"><strong>Stencil</strong></a>, 8 themes with integrated dark mode, support for 12 languages, and many more features.</p>
<h2 id="heading-installation-and-configure">Installation and configure</h2>
<p>The installation is easy; we just run the following command:</p>
<p>Angular CLI:</p>
<pre><code class="lang-bash">ng add @compodoc/compodoc
</code></pre>
<p>or NPM:</p>
<pre><code class="lang-bash">npm install -g @compodoc/compodoc
</code></pre>
<p>This command will create a <code>tsconfig.doc.json</code> file. In this file, we have to decide which parts of our application we want to include or exclude.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"include"</span>: [<span class="hljs-string">"src/**/*.ts"</span>],
  <span class="hljs-attr">"exclude"</span>: [<span class="hljs-string">"src/test.ts"</span>, <span class="hljs-string">"src/**/*.spec.ts"</span>, <span class="hljs-string">"src/app/file-to-exclude.ts"</span>]
}
</code></pre>
<p>Also, we can add a few scripts to execute our documentation:</p>
<pre><code class="lang-json"><span class="hljs-string">"compodoc:build"</span>: <span class="hljs-string">"compodoc -p tsconfig.doc.json"</span>,
<span class="hljs-string">"compodoc:build-and-serve"</span>: <span class="hljs-string">"compodoc -p tsconfig.doc.json -s"</span>,
<span class="hljs-string">"compodoc:serve"</span>: <span class="hljs-string">"compodoc -s"</span>
</code></pre>
<h2 id="heading-the-results">The results</h2>
<p>Once we have installed and configured our project, everything is done. We just need to run the serve script and see what Compodoc builds. Let's take a look at a few examples:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714388825605/b26afa49-b6bb-42b7-bc69-911b39428253.png" alt="Screenshot of the SoundCloud-ngrx documentation overview page. The left sidebar contains navigation links such as README, CHANGELOG, LICENSE, and various sections like Modules, Components, Classes, and more. The main section displays a diagram of the application structure with components and modules interconnected, and buttons for zooming in, resetting, and zooming out. Below the diagram, there are icons indicating the number of Modules, Components, Injectables, Pipes, Classes, and Interfaces." class="image--center mx-auto" /></p>
<blockquote>
<p>In the project overview, we have a sidebar menu with all of our modules, components, classes, interfaces, etc.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714389093660/c9942bc3-75fc-4fa3-a3d2-52b0187cfdbc.png" alt="A screenshot of the coding frontend documentation generated using Compodoc. The left sidebar includes sections like Getting started, Modules, Components, Classes, Injectables, Interfaces, Pipes, Routes, Miscellaneous, and Documentation coverage. The main content shows a detailed routing module tree diagram with various routes and components, such as AppRoutingModule, FightRoutingModule, HomeRoutingModule, and StartRoutingModule, along with their respective paths and components." class="image--center mx-auto" /></p>
<blockquote>
<p>Routing overview, we have a detailed map with all of our routes.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714388974646/f54e5532-cfa1-47e8-81a5-210f24153cc0.png" alt="A screenshot of a documentation page for the &quot;IconButtonComponent&quot; in a software project. The page includes a navigation menu on the left and details about the component on the right, such as file path, metadata, and a code snippet for the button template." class="image--center mx-auto" /></p>
<blockquote>
<p>Component overview, detailed information of each component.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714389001838/f50dc745-82cb-4da5-be21-b3acc8791db6.png" alt="A screenshot of a documentation coverage report generated using Compodoc. The report shows a list of files with their types, identifiers, and documentation coverage percentages. The coverage is color-coded: green for high coverage, yellow for partial coverage, and red for no coverage. The overall documentation coverage is 1%. The sidebar on the left includes sections like Overview, README, CHANGELOG, LICENSE, Dependencies, Modules, Components, Classes, Injectables, Interfaces, Pipes, Miscellaneous, Routes, and Documentation coverage." class="image--center mx-auto" /></p>
<blockquote>
<p>Documentation coverage to have the knowledge of which percentage we have documented.</p>
</blockquote>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We just built our project documentation in a few steps. Compodoc, as you can see, is a great tool, fully automated to create your project documentation. We only saw a few features, but Compodoc has a lot more. We will talk more about <strong>Compodoc</strong> in the next articles.</p>
<p>I have attached the official page below.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🚀</div>
<div data-node-type="callout-text"><a target="_blank" href="https://compodoc.app/">Check out the Compodoc official page!</a></div>
</div>]]></content:encoded></item><item><title><![CDATA[Angular pipes: learning the basics]]></title><description><![CDATA[In Angular, pipes are used to transform data in the template. It's a useful feature to save time when transforming data using complex algorithms. You can use the built-in ones, or create your own and use them throughout your application.
Angular has ...]]></description><link>https://rubenperegrina.com/angular-pipes-learning-the-basics</link><guid isPermaLink="true">https://rubenperegrina.com/angular-pipes-learning-the-basics</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular 2]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[webdevelopment]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[front-end]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Wed, 29 May 2024 18:44:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/VjWi56AWQ9k/upload/1c989332a9ffb71f00a34b3dfd237aba.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Angular, pipes are used to transform data in the template. It's a useful feature to save time when transforming data using complex algorithms. You can use the built-in ones, or create your own and use them throughout your application.</p>
<p>Angular has a lot of built-in pipes. Let's look at some of them and how to create your own.</p>
<h2 id="heading-how-it-works">How it works?</h2>
<p>The pipes are operators that you must use within the interpolation keys; you should use them in the HTML template.</p>
<p>Within the interpolation, you need to add <code>|</code> after the value and then the name of the pipe. A simple example would be</p>
<pre><code class="lang-xml">{{ name | uppercase }}
</code></pre>
<p>We can separate the 3 parts for better understanding</p>
<p><strong>Input</strong>: Refers to the input value to be transformed.</p>
<p><strong>Transform</strong>: This is the process we submit this information to.</p>
<p><strong>Output</strong>: This is the value that results from the transformation.</p>
<blockquote>
<p>Remember, to use the built-in pipes, you need to import them into your module or your component. If you are using standalone components, import the <strong>CommonModule</strong>. Alternatively, you can import just the specific pipe you need instead of the whole <strong>CommonModule</strong>.</p>
</blockquote>
<h2 id="heading-built-in-pipes">Built-in pipes</h2>
<p>Angular provides built-in pipes for typical data transformations. Here are a few examples with their explanations:</p>
<ul>
<li><p><a target="_blank" href="https://angular.dev/api/common/DatePipe"><code>DatePipe</code></a>: Formats a date value according to locale rules.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/api/common/UpperCasePipe"><code>UpperCasePipe</code></a>: Transforms text to all upper case.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/api/common/LowerCasePipe"><code>LowerCasePipe</code></a>: Transforms text to all lower case.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/api/common/CurrencyPipe"><code>CurrencyPipe</code></a>: Transforms a number to a currency string, formatted according to locale rules.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/api/common/DecimalPipe"><code>DecimalPipe</code></a>: Transforms a number into a string with a decimal point, formatted according to locale rules.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/api/common/PercentPipe"><code>PercentPipe</code></a>: Transforms a number to a percentage string, formatted according to locale rules.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/api/common/AsyncPipe"><code>AsyncPipe</code></a>: Subscribe and unsubscribe to an asynchronous source such as an observable.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/api/common/JsonPipe"><code>JsonPipe</code></a>: Display a component object property on the screen as JSON for debugging.</p>
</li>
</ul>
<h2 id="heading-using-pipes-with-parameters">Using pipes with parameters</h2>
<p>Parameters can be optional or required depending on the pipe. To specify the parameter on a pipe, you have to put it after the <code>:</code>. Let's take a look at a few examples:</p>
<p>The date pipe accepts parameters to control the date format:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>The hero's birthday is in {{ birthday | date:'yyyy' }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p>Also, the date pipe accepts a second parameter to control the timezone, you need to use another <code>:</code></p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>The current time is: {{ currentTime | date:'hh:mm':'UTC' }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<h2 id="heading-combining-two-pipes">Combining two pipes</h2>
<p>You can use multiple pipes at the same time, you just have to add another <code>|</code> to separate them:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>The hero's birthday is in {{ birthday | date:'yyyy' | uppercase }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<h2 id="heading-using-pipes-inside-typescript-files">Using pipes inside TypeScript files</h2>
<p>Maybe you need to transform the data for some other reason and you don't need to show it in the template, you can also do it in the template, you need to add the pipe to your component's providers array and then inject it using dependency injection. After that, you can use it like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> formattedDate = <span class="hljs-built_in">this</span>.datePipe.transform(<span class="hljs-built_in">this</span>.currentDate, <span class="hljs-string">'dd/MM/yyyy'</span>);
</code></pre>
<h2 id="heading-creating-our-custom-pipe">Creating our custom pipe</h2>
<p>If the built-in pipes that Angular gives us aren't enough, you can create your own, let's see an example:</p>
<p>Create it using the Angular CLI:</p>
<pre><code class="lang-bash">ng g p pipes/customPipe
</code></pre>
<p>This command creates the class for your custom pipe, inside the class, you should return the transformed value.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Pipe, PipeTransform } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-meta">@Pipe</span>({
  name: <span class="hljs-string">'customPipe'</span>,
  standalone: <span class="hljs-literal">true</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CustomPipe <span class="hljs-keyword">implements</span> PipeTransform {
  transform(value: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Hello <span class="hljs-subst">${value}</span>`</span>;
  }
}
</code></pre>
<p>We just create a simple pipe that returns the value we sent plus a 'Hello' text, we make it standalone but this is not required.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{{ userName | customPipe }}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span> //Hello Rubén
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Angular pipes are a great way to save time, by default Angular provides us with many useful pipes, but also gives us the ability to create our own. We have learned about the most useful pipes and seen an example of how to create one.</p>
]]></content:encoded></item><item><title><![CDATA[Most common RxJs operators used in Angular]]></title><description><![CDATA[RxJs is a fundamental part of Angular, although signals have been implemented since version 16, and it is expected that RxJs will be used less and less. For now, there are many projects using it, and it will be around for a while.
It is important to ...]]></description><link>https://rubenperegrina.com/most-common-rxjs-operators-used-in-angular</link><guid isPermaLink="true">https://rubenperegrina.com/most-common-rxjs-operators-used-in-angular</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular 2]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[RxJS]]></category><category><![CDATA[Reactive Programming]]></category><category><![CDATA[asynchronous]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Mon, 20 May 2024 17:56:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ImcUkZ72oUs/upload/825b77968b690c16475fc37bebb63878.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>RxJs is a fundamental part of Angular, although signals have been implemented since version 16, and it is expected that <a target="_blank" href="https://rxjs.dev/">RxJs</a> will be used less and less. For now, there are many projects using it, and it will be around for a while.</p>
<p>It is important to understand how it works and what its main advantages are. It's a powerful library for <strong>handling asynchronous operations</strong>, but there are many operators, and sometimes it's hard to understand what each one is for and which one is best to use at any given time. This article aims to explain with examples which ones are <strong>most commonly used</strong>.</p>
<blockquote>
<p>An operator is a function used in an observable that controls and emits only the information we are interested in, in the way we need it.</p>
</blockquote>
<h2 id="heading-map">map</h2>
<p>It is one of the most common operators in RxJs, and you have probably seen it many times. <code>map</code> allows us to transform the data emitted by the observable without altering it. Let's have a look at an example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> number$ = range(<span class="hljs-number">1</span>, <span class="hljs-number">5</span>);

<span class="hljs-built_in">number</span>$.pipe(map(<span class="hljs-function">(<span class="hljs-params"><span class="hljs-built_in">number</span></span>) =&gt;</span> <span class="hljs-built_in">number</span> * <span class="hljs-number">2</span>)).subscribe(<span class="hljs-built_in">console</span>.log);
<span class="hljs-comment">// output: 2, 4, 6, 8, 10</span>
</code></pre>
<p>As we can see, the expected output would be <code>1, 2, 3, 4, 5</code>, but by applying map, we transform the values of the observable, in this case multiplying the values by two.</p>
<p>Here is a more visual example from the <a target="_blank" href="https://rxjs.dev/api/operators/map">official RxJs documentation</a> where the arrow above is the initial data stream of the observable and the one below is after applying map.</p>
<p><img src="https://rxjs.dev/assets/images/marble-diagrams/map.png" alt="A diagram showing a mapping function. The top row has circles with numbers 1, 2, and 3. The middle row shows the function &quot;map(x =&gt; 10 * x)&quot;. The bottom row has circles with numbers 10, 20, and 30, indicating the result of applying the function to the numbers in the top row." /></p>
<h2 id="heading-filter">filter</h2>
<p>The filter operator is used to filter the values of the observable stream. With this operator, we only emit those values that march the condition we set. Let's look at an example.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> number$ = range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>);

<span class="hljs-built_in">number</span>$.pipe(filter(<span class="hljs-function">(<span class="hljs-params">n</span>) =&gt;</span> n &gt; <span class="hljs-number">5</span>)).subscribe(<span class="hljs-built_in">console</span>.log);
<span class="hljs-comment">// output: 6, 7, 8, 9, 10</span>
</code></pre>
<p>In this way, we filter the values of the observable and return only those that match the condition. Without the filter, the output would be <code>1, 2, 3, 4, 5...</code>. After applying the filter, only values greater than 5 are returned. Let's look at a visual example:</p>
<p><img src="https://rxjs.dev/assets/images/marble-diagrams/filter.png" alt="A diagram showing a sequence of numbers (0, 1, 2, 3, 4) being filtered through a function &quot;filter(x =&gt; x % 2 === 1)&quot;, resulting in a new sequence of odd numbers (1, 3)." /></p>
<h2 id="heading-tap">tap</h2>
<p>It is a utility operator that allows performing side actions that do not affect the main flow without affecting the emission or transformation of the observable.</p>
<p>It is a useful operator for debugging and testing the observable without modifying the output. Any logic we put inside the tap will help us debug and test, but the data stream remains intact. Let's look at an example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">of</span>(<span class="hljs-built_in">Math</span>.random()).pipe(
  tap(<span class="hljs-built_in">console</span>.log),
  map(<span class="hljs-function"><span class="hljs-params">n</span> =&gt;</span> n &gt; <span class="hljs-number">0.5</span> ? <span class="hljs-string">'big'</span> : <span class="hljs-string">'small'</span>)
).subscribe(<span class="hljs-built_in">console</span>.log);
</code></pre>
<p>In this example with the map operator, we filter the numbers received from the observable to log "big" or "small" to the console depending on whether they are greater or less than 0.5. This is fine, but for development reasons, we want to know what number was initially received before filtering. By adding the tap, we can find out what it was. Let's look at a visual example from the <a target="_blank" href="https://rxjs.dev/api/index/function/tap">official documentation</a>:</p>
<p><img src="https://rxjs.dev/assets/images/marble-diagrams/tap.png" alt="Diagram showing the use of the `tap` operator in RxJS. The top line has three colored circles labeled 1, 2, and 3. The middle box contains the code `tap(x =&gt; console.log(x))`. The bottom line shows the same three colored circles with a blue outline, indicating the values are logged but unchanged." /></p>
<h2 id="heading-take">take</h2>
<p>The take operator emits the first n values and then completes the observable. The argument <code>count</code> specifies the number of values the observable should emit before completing. If the observable emits fewer values than the specified maximum, it will simply emit those and complete, regardless of whether the source has completed or not.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> intervalCount = interval(<span class="hljs-number">1000</span>);
<span class="hljs-keyword">const</span> takeFive = intervalCount.pipe(take(<span class="hljs-number">5</span>));
takeFive.subscribe(<span class="hljs-function"><span class="hljs-params">x</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(x));

<span class="hljs-comment">// output:</span>
<span class="hljs-comment">// 0</span>
<span class="hljs-comment">// 1</span>
<span class="hljs-comment">// 2</span>
<span class="hljs-comment">// 3</span>
<span class="hljs-comment">// 4</span>
</code></pre>
<p>In this example, using the interval operator, it should emit a value every second, but by adding the take operator with a count of 5, it only emits 5 values and then completes. The take operator can also be used together with others such as filter, map, and mergeMap to manipulate and control the values emitted by an observable. Let's have a look at a visual example from the <a target="_blank" href="https://rxjs.dev/api/index/function/take">official documentation</a>:</p>
<p><img src="https://rxjs.dev/assets/images/marble-diagrams/take.png" alt="A diagram showing the &quot;take(2)&quot; operation on a sequence of elements. The original sequence contains elements &quot;a&quot;, &quot;b&quot;, &quot;c&quot;, and &quot;d&quot;. After applying the &quot;take(2)&quot; operation, the resulting sequence contains only the first two elements: &quot;a&quot; and &quot;b&quot;." /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>These are just some of the most commonly used RxJs operators, but there are many more. Understanding how they work can be very useful, especially when working on Angular applications. These operators make data handling easier and save us a lot of time. However, RxJs has a high learning curve; the first time you use it can be a bit overwhelming. That's why it's important to learn the basics well from the start. We will look at more operators in the following articles.</p>
<p><strong>Other RxJs articles you may be interested in:</strong></p>
<ul>
<li><p><a target="_blank" href="https://rubenperegrina.com/handling-errors-in-angular-with-retry-operator">Handling errors in Angular with the retry operator</a></p>
</li>
<li><p><a target="_blank" href="https://rubenperegrina.com/creating-a-custom-rxjs-operator-for-live-search">Creating a custom RxJs operator for live search</a></p>
</li>
<li><p><a target="_blank" href="https://rubenperegrina.com/enhancing-subscription-management-with-takeuntildestroy-in-angular">Enhancing subscription management with takeUntilDestroy in Angular</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to build a static blog in Angular with Scully]]></title><description><![CDATA[Before I started my Hashnode blog, I tried to build my own blog. While searching for the best option, I experimented with Scully. Why did I choose Hashnode instead of Scully? That answer will be in another post. For now, let's concentrate on understa...]]></description><link>https://rubenperegrina.com/how-to-build-a-static-blog-in-angular-with-scully</link><guid isPermaLink="true">https://rubenperegrina.com/how-to-build-a-static-blog-in-angular-with-scully</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Sun, 12 May 2024 19:12:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/fMD_Cru6OTk/upload/1839ce5e42b927af92e6a03dbb579c3f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Before I started my Hashnode blog, I tried to build my own blog. While searching for the best option, I experimented with <strong>Scully</strong>. Why did I choose Hashnode instead of Scully? That answer will be in another post. For now, let's concentrate on understanding what Scully is and how to build a blog using it.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/rubenperegrina/scully-blog/tree/master">https://github.com/rubenperegrina/scully-blog/tree/master</a></div>
<p> </p>
<h2 id="heading-what-is-scully">What is Scully?</h2>
<p>Scully is a library for Angular used to build blogs with static content. It enables you to create a <strong>solid structure for generating a blog</strong>. One of its best features is generating a static HTML file for each route. This functionality significantly enhances rendering <strong>speed and SEO</strong>.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🚀</div>
<div data-node-type="callout-text"><a target="_blank" href="https://scully.io/">Check out the Scully documentation!</a></div>
</div>

<h2 id="heading-how-it-works">How it works?</h2>
<p>First of all, we need an Angular application and then install the Scully library:</p>
<pre><code class="lang-bash">ng new scully-app
npm i @scullyio/scully @scullyio/ng-lib @scullyio/scully-plugin-puppeteer
</code></pre>
<p>We need to add the <strong>ScullyLibModule</strong> to our app.module, Scully doesn't support bootstrapping via a standalone component, Scully needs to be bootstrapped in a module, and then you can use standalone components.</p>
<p>There is a schematic for this:</p>
<pre><code class="lang-typescript">ng add <span class="hljs-meta">@scullyio</span>/init
</code></pre>
<p>With this command, we add the <code>ScullyLibModule</code> and also create the <code>scully.[PROJECT_NAME].config.ts</code></p>
<p>From Angular 14 onwards the <code>defaultProject</code> property has been deprecated from the angular.json. Scully needs this property, we need to configure it:</p>
<pre><code class="lang-json">{ <span class="hljs-attr">"defaultProject"</span>: <span class="hljs-string">"[PROJECT_NAME]"</span> }
</code></pre>
<p>Finally, we need to add some scripts to our package.json:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"scully"</span>: <span class="hljs-string">"scully"</span>,
    <span class="hljs-attr">"scully:serve"</span>: <span class="hljs-string">"scully serve"</span>
  }
</code></pre>
<h2 id="heading-how-to-create-the-content">How to create the content?</h2>
<p>To create content, you can use the CLI command <code>ng generate @scullyio/init:post --name="This is my post"</code> or just create the file with <code>.md</code></p>
<p>This will generate the file with 3 tags:</p>
<ul>
<li><p><code>title</code>: this is the title of the blog post</p>
</li>
<li><p><code>description</code>: this is the description</p>
</li>
<li><p><code>published</code>: this is a property representing whether the blog post is published or not. It takes a <code>true</code> or <code>false</code>.</p>
</li>
</ul>
<p>Then you just have to generate the route for your post with: <code>npx scully</code></p>
<p>You can also add other tags if needed, such as image, date, keywords and authors. This is useful if you want to add more features to your blog.</p>
<p>To test the blog, simply run: <code>npx scully:serve</code></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>To summarize, we have seen a brief introduction to Scully, what it is, and how it works, we need to talk more about Scully but we have a quick introduction and the first steps to building a blog with Scully, we will talk more in depth in the next articles.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🚀</div>
<div data-node-type="callout-text"><a target="_blank" href="https://scully.io/">Check out the Scully documentation!</a></div>
</div>]]></content:encoded></item><item><title><![CDATA[Angular will be merged with Wiz]]></title><description><![CDATA[What a game-changer! Yes, the title is true, this is what we saw at the ng-conf.
The ng-conf is an annual conference focused on Angular. It brings together experts, developers, and enthusiasts to discuss the latest Angular trends and practices. Highl...]]></description><link>https://rubenperegrina.com/angular-will-be-merged-with-wiz</link><guid isPermaLink="true">https://rubenperegrina.com/angular-will-be-merged-with-wiz</guid><category><![CDATA[wiz]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular 2]]></category><category><![CDATA[Google]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[front-end]]></category><category><![CDATA[webdev]]></category><category><![CDATA[framework]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Fri, 22 Mar 2024 13:18:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1711107592908/b98ad8f1-48c4-4620-b91e-d467dd710640.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>What a game-changer! Yes, the title is true, this is what we saw at the <a target="_blank" href="https://ng-conf.org/">ng-conf</a>.</p>
<p>The <a target="_blank" href="https://ng-conf.org/">ng-conf</a> is an annual conference focused on Angular. It brings together experts, developers, and enthusiasts to discuss the latest Angular trends and practices. Highlights include talks, workshops, and panel discussions on new features, best practices, and the future of Angular. It's a key event for staying up to date in the world of web development.</p>
<p>In this conference, <strong>Minko Gechev</strong> and <strong>Jeremy Elbourn</strong>, both working in the Angular team, present the news that Angular will be merged with Wiz, Google's internal framework.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=nIBseTi6RVk&amp;ab_channel=ng-conf">https://www.youtube.com/watch?v=nIBseTi6RVk&amp;ab_channel=ng-conf</a></div>
<p> </p>
<h2 id="heading-what-is-wiz">What is Wiz?</h2>
<p>Wiz is a front-end internal framework made by Google, they are used in many products, one of them are <strong>Google Drive, Google Photos, Google Maps, YouTube and Gmail</strong>.</p>
<p>Wiz had been used for a while, but we don't know much about them because it is not open source, we know that they have the <strong>Signals</strong> of Angular and a <strong>resumability</strong> feature.</p>
<h2 id="heading-what-we-can-expect">What we can expect?</h2>
<p>We can expect a merge between <strong>Angular</strong> and <strong>Wiz</strong>, adding all the Wiz features in Angular, mainly the <strong>resumability</strong>. With this feature Angular will increase it's performance a lot.</p>
<p>There's not much information at the moment, that's the official news, but I want to speculate a bit...</p>
<p>I think that this is going to be a huge improvement for Angular, in terms of marketing and performance, Angular it's from Google but we don't know which products they used, Angular has the potential to be used in many sites and many companies can adopt it, but Google has not done the marketing for it.</p>
<p>Now if Google starts this merge and starts to use Angular in more sites, Angular is going to have a big impact and it's going to be more popular. In the other site with this merge maybe Angular will change a little bit its syntax or the way that we have been developing up to now, the releases may start to do slowly.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/sarah_edo/status/1770478763253379488">https://twitter.com/sarah_edo/status/1770478763253379488</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>It's great news that Google will do this, I hope it will be the next step for Angular and the community, but we need time to have a look at it, we will wait for the next news about it, and I will attach some references about it.</p>
<p>Do you like this change? Do you already know Wiz? Let me know in the comments!</p>
<p><a target="_blank" href="https://ng-conf.org/">ng-conf website</a></p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=nIBseTi6RVk&amp;ab_channel=ng-conf">ng-conf video</a></p>
<p><a target="_blank" href="https://twitter.com/sarah_edo/status/1770478763253379488">X thread</a></p>
]]></content:encoded></item><item><title><![CDATA[Essential insights into package.json: Navigating project dependencies]]></title><description><![CDATA[A few days ago I had a problem with a package.json at my work and I had to investigate some details to solve it. I found out that there are a few things that are didn't know. In this article I will try to explain what a package.json file is, what it ...]]></description><link>https://rubenperegrina.com/essential-insights-into-packagejson-navigating-project-dependencies</link><guid isPermaLink="true">https://rubenperegrina.com/essential-insights-into-packagejson-navigating-project-dependencies</guid><category><![CDATA[Node.js]]></category><category><![CDATA[node]]></category><category><![CDATA[node js]]></category><category><![CDATA[package]]></category><category><![CDATA[npm]]></category><category><![CDATA[front-end]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Sun, 17 Mar 2024 09:13:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/JwMGy1h-JsY/upload/e791a0775587619773dea55fc92e9c6b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few days ago I had a problem with a <strong>package.json</strong> at my work and I had to investigate some details to solve it. I found out that there are a few things that are didn't know. In this article I will try to explain what a package.json file is, what it is for and how to manage it in a front-end project.</p>
<h2 id="heading-what-is-a-packagejson">What is a package.json?</h2>
<p>The package.json file is generated by default for all <strong>node.js</strong> projects, when you run the command <code>npm init</code> automatically starts asking you a few questions about the project, then it generates the package.json file.</p>
<p>If you are here, you may be front-end and may know package.json because your <strong>Angular, React or Vue</strong> project.</p>
<blockquote>
<p>The main purpose of this file is to contain information about the npm packages installed for the project.</p>
</blockquote>
<p>A typical <strong>package.json</strong> file might look like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"my-app"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"0.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">"keywords"</span>: [],
  <span class="hljs-attr">"author"</span>: <span class="hljs-string">"Rubén Peregrina"</span>,
  <span class="hljs-attr">"license"</span>: <span class="hljs-string">"ISC"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-comment">//</span>
  },
  <span class="hljs-attr">"private"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-comment">//</span>
  },
  <span class="hljs-attr">"devDependencies"</span>: {
    <span class="hljs-comment">//</span>
  }
}
</code></pre>
<h2 id="heading-what-is-each-field">What is each field?</h2>
<p>Let's look at each field in package.json:</p>
<ul>
<li><p><strong>name</strong>: The name of the project, library, or package, ideally matching the repository.</p>
</li>
<li><p><strong>version</strong>: Version of the package.</p>
</li>
<li><p><strong>description</strong>: Short project description.</p>
</li>
<li><p><strong>main</strong>: Entry point for the project, usually <code>index.js</code> (for Node) or <code>index.html</code> (for browsers).</p>
</li>
<li><p><strong>scripts</strong>: Collection of project scripts.</p>
</li>
<li><p><strong>keywords</strong>: Relevant keywords for project searchability.</p>
</li>
<li><p><strong>author</strong>: Author's name, usually including contact information or a URL.</p>
</li>
<li><p><strong>license</strong>: Project license type, commonly ISC.</p>
</li>
<li><p><strong>dependencies</strong>: Packages required for production environment.</p>
</li>
<li><p><strong>devDependencies</strong>: Packages needed for development environment.</p>
</li>
<li><p><strong>homepage</strong>: URL of the project's homepage.</p>
</li>
<li><p><strong>repository</strong>: Repository URL (type and route).</p>
</li>
<li><p><strong>bugs</strong>: Object containing the project's issues page URL.</p>
</li>
</ul>
<h2 id="heading-managing-dependencies">Managing dependencies</h2>
<p>The main focus of this file is to specify dependencies, providing an efficient way of managing project dependencies.</p>
<p>There are several types of dependencies, let's review each of them:</p>
<p><strong>dependencies</strong>: Essential project dependencies, added using <code>npm install my-dependency</code></p>
<p><strong>devDependencies</strong>: Dependencies used during development, added using the <code>--save-dev</code> flag</p>
<p><strong>optionalDependencies</strong>: These are dependencies that will not cause installation failure of an application or project. NPM will ignore them if they fail. The application will still work as expected regardless of whether these dependencies are present or not. Use the <code>--save-optional</code> flag to install them as optional.</p>
<p><strong>bundledDependencies</strong>: Used to specify an array of dependencies that should be bundled together with the package itself when it is released or distributed. If an NPM package has dependencies listed in bundledDependencies, those dependencies will be automatically installed along with the main package.</p>
<p><strong>peerDependencies</strong>: Used to specify dependencies that are necessary for the package to work properly, but must be provided by the environment in which the package is installed. NPM will give a warning if some peer dependencies are missing.</p>
<h2 id="heading-formats-for-specifying-versions">Formats for specifying versions</h2>
<p>There are several formats to specify which version you are using:</p>
<p>1.2.2: Exactly version 1.2.2</p>
<p>^1.2.2: The latest version compatible with version 1.2.2</p>
<p>~1.2.2: Works for versions such as 1.2.2, 1.2.3, 1.2.4,...</p>
<p>~1.2: Works for versions like 1.3, 1.4, 1.5,...</p>
<p>1.2.x: Works with any patched version of 1.2</p>
<p>1.x: Works for any minor version of the package’s 1 version</p>
<p>\&gt;=1.2: Version 1.2 or higher. You can also use &lt;, &lt;= or &gt;</p>
<p>1.2.2 4.1.1: Versions 1.2.2 through 4.1.1 (inclusive)</p>
<blockquote>
<p>Multiple possible version ranges can be specified by separating each range with ||</p>
</blockquote>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The package.json file serves as a crucial component in <strong>Node.js</strong> projects, facilitating efficient management of dependencies and project configurations. Understanding its structure and functionality is essential for seamless project development and maintenance.</p>
<p>With this article you have learnt a bit more about the structure of the <strong>package.json</strong> and how it works, there are still questions in the air that we can clear up in the next articles.</p>
]]></content:encoded></item><item><title><![CDATA[What type of builders there are in Angular?]]></title><description><![CDATA[Since the release of Angular 17, now we have three different builders to choose from when building our applications. These builders are based on Webpack, EsBuild, and serve the purpose of Server-Side Rendering (SSR). In this article, we will explore ...]]></description><link>https://rubenperegrina.com/what-type-of-builders-there-are-in-angular</link><guid isPermaLink="true">https://rubenperegrina.com/what-type-of-builders-there-are-in-angular</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular 2]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[vite]]></category><category><![CDATA[esbuild]]></category><category><![CDATA[SSR]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[front-end]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[web]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Mon, 04 Mar 2024 14:09:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/sTw2KYpoujk/upload/3984113f3b35e01d12fc24d2f0ff60cb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Since the release of Angular 17, now we have three different builders to choose from when building our applications. These builders are based on <strong>Webpack</strong>, <strong>EsBuild</strong>, and serve the purpose of <strong>Server-Side Rendering (SSR)</strong>. In this article, we will explore the differences between them and answer the common question: <strong>which is better and when should you use each?</strong> We will start by exploring these builders.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>Developers must carefully consider the builder when creating a robust Angular application, as this choice significantly impacts performance and development efficiency. Angular 17 introduces three different builders, and this article will focus on a comprehensive overview to help developers make the right decisions.</p>
<h2 id="heading-builders-overview">Builders overview:</h2>
<p>When you go to the <a target="_blank" href="https://angular.dev/tools/cli/build#">new Angular website</a> and exploring the available builders, you will come across three main types, excluding the fourth, which is dedicated to libraries. Let's look at each of them:</p>
<p><strong>@angular-devkit/build-angular:browser (Webpack-Based):</strong></p>
<p>This is the oldest and most commonly used builder, provide bundling client-side applications for browser use with Webpack. It provides a <strong>smooth transition to new Angular features</strong>, particularly if there are dependencies or customizations in Webpack.</p>
<p><strong>@angular-devkit/build-angular:browser-esbuild (EsBuild-Based):</strong></p>
<p>Similar to the Webpack-based builder, but with a significant distinctio. it use EsBuild instead of Webpack. EsBuild, <strong>being notably faster</strong> due to its build in Go, offers around a <strong>57% speed improvement</strong> according to Angular team tests. Ideal for optimizing local development times and integrating with continuous integration workflows.</p>
<p><strong>@angular-devkit/build-angular:application (SSR Builder):</strong></p>
<p>Introduced as a new feature in Angular 17, this builder prioritizes efficient development, supporting both <strong>server-side and client-side rendering</strong>. Aligned with the industry trend towards server-side rendering by default, <strong>promising enhancements in initial load times and SEO</strong>.</p>
<h2 id="heading-detailed-comparison">Detailed comparison:</h2>
<p>For a more detailed understanding, let's compare <strong>@angular-devkit/build-angular:browser</strong> and <strong>@angular-devkit/build-angular:browser-esbuild</strong>. This comparison goes further than simply choosing between Webpack and EsBuild; it examines the potential impact on development speed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709322870832/57da6b5d-e279-4db0-9b97-040d0de8eca8.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion:</h2>
<p>The choice of Angular builder depends on your project's specific requirements and goals. The <strong>Webpack-based</strong> builder remains a solid option for many scenarios, while the <strong>EsBuild-based</strong> builder offers in terms of speed and efficiency. For projects demanding server-side rendering, the <strong>@angular-devkit/build-angular:application</strong> builder becomes to be a game changer.</p>
<p>Consider the aspects of your project, evaluate the builders' strengths, and make a decision based on your development needs. Remember, the key is to understand the differences of each builder and align them with your project's goals.</p>
<p><a target="_blank" href="https://angular.dev/tools/cli/build#">Angular official documentation</a></p>
<p><a target="_blank" href="https://esbuild.github.io/">EsBuild comparison</a></p>
]]></content:encoded></item><item><title><![CDATA[Why use TypeScript?]]></title><description><![CDATA[TypeScript has established itself as an essential tool for improving code quality and maintainability. At the beginning, it may appear to be a layer on top of JavaScript, but its benefits extend far beyond that. In this article, we will explore what ...]]></description><link>https://rubenperegrina.com/why-use-typescript</link><guid isPermaLink="true">https://rubenperegrina.com/why-use-typescript</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[TypeScript Tutorial]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[javascript framework]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Developer]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Mon, 26 Feb 2024 15:31:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/8Zt0xOOK4nI/upload/3552d13f840ccc5796f9262ed1cb06e9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>TypeScript has established itself as an essential tool for improving code quality and maintainability. At the beginning, it may appear to be a layer on top of JavaScript, but its benefits extend far beyond that. In this article, we will explore what <strong>TypeScript</strong> is and why you should consider incorporating it into your workflow.</p>
<h2 id="heading-what-is-typescript">What is TypeScript?</h2>
<p>TypeScript is an additional layer that allows you to write code in your favorite editor. However, once compiled, all TypeScript code is transformed into <strong>pure JavaScript.</strong> This is important because JavaScript engines cannot interpret TypeScript code directly. It has to go through a "pre-translation" process called <strong>compilation</strong>. Only after this stage do you get clean JavaScript code ready to run in a browser. In essence, TypeScript is a special variant of JavaScript that requires a "translator" before execution.</p>
<h2 id="heading-why-use-typescript">Why use TypeScript?</h2>
<p>The benefits of using TypeScript quickly become apparent, especially when it comes to detecting both serious and minor errors in your code. It also gives your code base a solid structure and makes it almost self-documenting. Improved autocompletion in your editor is just an added benefit.</p>
<p>While there are proponents and detractors, the fact remains that TypeScript is a robust tool that, once mastered, can significantly i<strong>ncrease your productivity and code quality</strong>. In this article, we will explore some of the key benefits that make TypeScript a valuable addition to your development toolkit.</p>
<h2 id="heading-advantages-of-typescript">Advantages of TypeScript:</h2>
<p><strong>1. Static typing:</strong></p>
<p>TypeScript provides static typing, allowing you to specify the type of a variable, function parameter, or object property. This helps in detecting errors during compilation, providing more robust code, and preventing runtime issues.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">let</span> age: <span class="hljs-built_in">number</span> = <span class="hljs-number">25</span>;
<span class="hljs-keyword">let</span> name: <span class="hljs-built_in">string</span> = <span class="hljs-string">"Rubén"</span>;
<span class="hljs-keyword">let</span> isUpdated: <span class="hljs-built_in">boolean</span> = <span class="hljs-literal">false</span>;
</code></pre>
<p><strong>2. Early error detection:</strong></p>
<p>Static typing allows TypeScript to detect errors during the compilation process, preventing potential issues before the code runs.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">let</span> age: <span class="hljs-built_in">number</span> = <span class="hljs-string">"Hello"</span>; <span class="hljs-comment">// Error: Incorrect data type</span>
</code></pre>
<p><strong>3. Enhanced autocompletion:</strong></p>
<p>TypeScript's type system improves autocompletion in editors, offering more accurate suggestions and reducing development errors.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> fruits: <span class="hljs-built_in">string</span>[] = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cherry"</span>];
fruits. <span class="hljs-comment">// You get autocompletion suggestions</span>
</code></pre>
<p><strong>4. Clear code structuring:</strong></p>
<p>TypeScript allows you to define clear data types and structures in your code, making it easier to understand and maintain.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> Person {
  name: <span class="hljs-built_in">string</span>;
  age: <span class="hljs-built_in">number</span>;
}
</code></pre>
<p><strong>5. Type inference:</strong></p>
<p>While type annotations can be added, TypeScript can automatically infer the type of a variable based on its value, making the code more concise.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">let</span> message = <span class="hljs-string">"Hello"</span>; <span class="hljs-comment">// TypeScript infers that 'message' is of type string</span>
</code></pre>
<p><strong>6. Code maintenance improvement:</strong></p>
<p>Static typing and clear structures in TypeScript contribute to more maintainable code, making it easier for developers to understand and work on the project.</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">person: <span class="hljs-built_in">string</span></span>): <span class="hljs-title">string</span> </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, "</span> + person;
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>These benefits demonstrate how TypeScript can improve software development by providing developers with stronger tools for creating robust and efficient code. We will discover more benefits in the next articles.</p>
<ul>
<li><p>Official documentation <a target="_blank" href="https://www.typescriptlang.org/%EF%BF%BC%E2%80%A2">https://www.typescriptlang.org/</a></p>
</li>
<li><p>Playground <a target="_blank" href="https://www.typescriptlang.org/play">https://www.typescriptlang.org/play</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Angular 17.2 is already here]]></title><description><![CDATA[It's only been a month since Angular 17.1 was released, and already we have another version.
In this article, we will explore a few features like experimental support for Material 3, signal queries, model inputs, Netlify loader, and hydration debuggi...]]></description><link>https://rubenperegrina.com/angular-172-is-already-here</link><guid isPermaLink="true">https://rubenperegrina.com/angular-172-is-already-here</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular 2]]></category><category><![CDATA[angular material]]></category><category><![CDATA[Google]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[web]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[front-end]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Tue, 20 Feb 2024 18:42:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1708451886240/697bd37c-6d8c-4115-88d2-cf32e98dda1c.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It's only been a month since Angular 17.1 was released, and already we have another version.</p>
<p>In this article, we will explore a few features like experimental support for <strong>Material 3</strong>, signal queries, model inputs, <strong>Netlify loader</strong>, and <strong>hydration debugging</strong> support in Angular DevTools.</p>
<h2 id="heading-experimental-material-3">Experimental Material 3</h2>
<p>In this release, Angular has experimental support for <strong>Material 3</strong> theming in Angular Material.</p>
<p>The Angular team has been working closely with <strong>Google's Material Design</strong> team to make this happen.</p>
<p>Material 3 is the most recent version of Material Design, Google's open-source design system. Material 3 for Angular is an alternative theme that is compatible with the same Angular Material components and Sass mixins currently in use.</p>
<blockquote>
<p>We will explore more about Material 3 in the following articles.</p>
</blockquote>
<h2 id="heading-improving-signals">Improving signals</h2>
<p>Since a few versions ago Angular has tried to improve reactivity.</p>
<p>Angular is continuously improving with each version, and developers can try out new features in developer previews. Signals is an example of this.</p>
<p><strong>Signal queries</strong> and <strong>model inputs</strong> are included in this version.</p>
<h2 id="heading-angular-devtools-now-supports-hydration-debugging">Angular DevTools now supports hydration debugging</h2>
<p>Thanks to this improvement, we can now debug <strong>Angular DOM mismatch errors.</strong></p>
<p>Angular DevTools now displays the difference between the DOM from the browser and the HTML generated by the server.</p>
<h2 id="heading-improvements-for-ngoptimizedimage">Improvements for NgOptimizedImage</h2>
<p>The <strong>NgOptimizedImage</strong> directive was an improvement that enabled us to optimize image management.</p>
<p>You can optimize the image loader with Netlify by using <strong>provideNetlifyLoader</strong> instead of including an image loader with srcset.</p>
<p>The placeholder attribute can be used to quickly add a <strong>blurred image while the actual image loads</strong>. This will automatically request a smaller version of the image, blur it, and display it until the full image is ready.</p>
<h2 id="heading-anything-else">Anything else?</h2>
<p>The Angular CLI now supports <strong>Bun's package manager</strong> and allows for control of the <strong>Vite development server prebundling</strong>. Additionally, the application builder now supports <strong>custom postcss configuration</strong>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Angular continues to release new features and updates frequently, demonstrating a commitment to listening to the community's needs. The upcoming release, <strong>Angular 18 in May</strong>, is highly anticipated.</p>
<p>What improvements do you anticipate?</p>
]]></content:encoded></item><item><title><![CDATA[How to use environments in Angular]]></title><description><![CDATA[Creating and managing environments in Angular applications could be difficult, especially if we have a lot of them and you never work with them.
In this article, we will take a look at how Angular applications manage this and we will create a few exa...]]></description><link>https://rubenperegrina.com/how-to-use-environments-in-angular</link><guid isPermaLink="true">https://rubenperegrina.com/how-to-use-environments-in-angular</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular 2]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Developer]]></category><category><![CDATA[development]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Mon, 12 Feb 2024 12:29:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/auEPahZjT40/upload/026d204e0c57767161470ce66dc25690.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Creating and managing environments in Angular applications could be difficult, especially if we have a lot of them and you never work with them.</p>
<p>In this article, we will take a look at how Angular applications manage this and we will create a few examples to learn it. But, before we dive into that, let's cover some basics.</p>
<h2 id="heading-what-is-an-environment">What is an environment?</h2>
<p>An environment is a configuration that you can make to work with different scenarios in your application, imagine that you are developing an application and you need to have dev, test and staging environments to deal with your data base or API.</p>
<p>When you run a builder target, such as build, serve, and test, Angular replaces the environment default file for the one you selected.</p>
<blockquote>
<p>Since Angular 14 we don't have the environments folder by default when we create a new project, we need to create it with: <code>ng generate environments</code></p>
</blockquote>
<h2 id="heading-how-can-i-create-it">How can I create it?</h2>
<p>Once we have our environments folder created in <em>src/environments</em>, we have a default configuration environment <code>environment.ts</code></p>
<p>This file provides us the default configuration for production, we can add different ones like staging, development.</p>
<pre><code class="lang-typescript">my-app/src/environments
├── environment.development.ts
├── environment.staging.ts
└── environment.ts
</code></pre>
<p>The base file contains the default configuration like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> environment = {
  production: <span class="hljs-literal">true</span>
};
</code></pre>
<p>The build targets use this file as a default if we do not specify one.</p>
<p>Now we can add more values to the environment like the APIs, and URLs that we need to use:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> environment = {
  production: <span class="hljs-literal">true</span>,
  apiUrl: <span class="hljs-string">'http://my-prod-url'</span>
};
</code></pre>
<blockquote>
<p>Always check that we have our environments configurates in angular.json file like this:</p>
</blockquote>
<pre><code class="lang-typescript"><span class="hljs-string">"configurations"</span>: {
    <span class="hljs-string">"development"</span>: {
      <span class="hljs-string">"fileReplacements"</span>: [
          {
            <span class="hljs-string">"replace"</span>: <span class="hljs-string">"src/environments/environment.ts"</span>,
            <span class="hljs-string">"with"</span>: <span class="hljs-string">"src/environments/environment.development.ts"</span>
          }
        ],
        ...
</code></pre>
<h2 id="heading-using-specific-environments-in-our-app">Using specific environments in our app</h2>
<p>Now it's the time to use our environment values in the components and services.</p>
<p>To ensure the build, serve and test commands use the correct file, we have to use the original environment file.</p>
<p>We just to import the file into our component or service like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { environment } <span class="hljs-keyword">from</span> <span class="hljs-string">'./environments/environment'</span>;
</code></pre>
<p>Then we can access to values that we defined before.</p>
<h2 id="heading-build-serve-and-test-with-a-specific-environment">Build, serve and test with a specific environment</h2>
<p>Once we create our environment, add some values, and use these values in our components it's time to select which environment we want to use for build, serve or test our application.</p>
<p>Here there are a few examples:</p>
<pre><code class="lang-typescript">ng build --configuration development
ng serve --configuration development
ng test --configuration development
</code></pre>
<p>With this commands, Angular replaces the s<em>rc/environments/environment.ts</em> file with the development specific one.</p>
<p>We can do the same for other environments like staging production etc.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Now we have more knowledge about how Angular manages the environments in our applications, and with this we can develop more complex and security applications.</p>
]]></content:encoded></item><item><title><![CDATA[Create your own AI chat with Gemini and Nebular]]></title><description><![CDATA[As you know I have been using the Gemini API for the last two months, I wrote an article about it but it was a simple application just to know how the Gemini API works.

This is the second part of the exploroing the Gemini API, you can take a look at...]]></description><link>https://rubenperegrina.com/create-your-own-ai-chat-with-gemini-and-nebular</link><guid isPermaLink="true">https://rubenperegrina.com/create-your-own-ai-chat-with-gemini-and-nebular</guid><category><![CDATA[nebular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular 2]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[gemini]]></category><category><![CDATA[AI]]></category><category><![CDATA[chatbot]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[front-end]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Tue, 06 Feb 2024 10:10:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/hND1OG3q67k/upload/7ad6ccef7b973ad186b823d134f69d02.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As you know I have been using the <strong>Gemini API</strong> for the last two months, I wrote an article about it but it was a simple application just to know how the Gemini API works.</p>
<blockquote>
<p>This is the second part of the exploroing the Gemini API, you can take a look at the first part <a target="_blank" href="https://rubenperegrina.com/playing-with-googles-gemini-pro-api">here</a>.</p>
</blockquote>
<p>In this article we take a deep dive into the Gemini API using the <strong>UI library Nebular for Angular</strong>, Nebular brings us a powerfull library with over <strong>40+ components</strong>, I chose that specifically for the chat component.</p>
<p>The plan is to build a real time conversational chat application, the chat will be specialized in <strong>Angular and TypeScript</strong> to bring us the best answers.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🚀</div>
<div data-node-type="callout-text"><a target="_blank" href="https://github.com/rubenperegrina/gemini-chat"><strong>See the article code on GitHub</strong></a></div>
</div>

<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707130063340/d3d8e5a2-0cc4-462d-8b09-56282bb09dee.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-how-to-get-the-api-key">How to get the API key?</h2>
<p>Go to <a target="_blank" href="https://ai.google.dev/"><strong>https://ai.google.dev/</strong></a> and get your API key</p>
<p>Once we have the key we need to create a project to use it, in this case, we are going to use <a target="_blank" href="https://rubenperegrina.com/whats-new-in-angular-17"><strong>Angular</strong></a>.</p>
<h2 id="heading-creating-our-gemini-project">Creating our Gemini project</h2>
<p>First, we will create our project to be able to use <strong>Gemini</strong>, I assume you have everything you need to work with Angular installed, if not you can see it here:</p>
<p><a target="_blank" href="https://angular.dev/tutorials/first-app"><strong>https://angular.dev/tutorials/first-app</strong></a></p>
<p>We will create our project using Angular CLI:</p>
<pre><code class="lang-typescript">ng n gemini-chat
</code></pre>
<h2 id="heading-installing-and-configuring-nebular">Installing and configuring Nebular</h2>
<p>Once we have created the project, we need to install the Nebular UI library.</p>
<p>Here we have the documentation in case you get lost.</p>
<pre><code class="lang-typescript">ng add <span class="hljs-meta">@nebular</span>/theme
</code></pre>
<p>Add the Nebular module to our main module:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@NgModule</span>({
  imports: [
    NbThemeModule.forRoot(),
  ]
})
</code></pre>
<p>Include the Nebular styles in <code>angular.json</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-string">"styles"</span>: [
  <span class="hljs-string">"node_modules/@nebular/theme/styles/prebuilt/default.css"</span>,
],
</code></pre>
<h2 id="heading-installing-the-gemini-library"><strong>Installing the Gemini library</strong></h2>
<p>Install the <strong>Google Gemini library</strong> using the following command:</p>
<pre><code class="lang-typescript">npm i <span class="hljs-meta">@google</span>/generative-ai
</code></pre>
<p>Make sure everything goes well and check your <code>package.json</code> to see if the <strong>google/generative-ai</strong> is installed.</p>
<h2 id="heading-implementing-the-gemini-sdk">Implementing the Gemini SDK</h2>
<p>First of all we need to implement the API, so let's generate the environments and introduce your API key:</p>
<pre><code class="lang-typescript">ng g environments
</code></pre>
<p>Set it up:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> environment = {
    gemini_key: <span class="hljs-string">"your-key"</span>
};
</code></pre>
<p>Now create a service to consume the API:</p>
<pre><code class="lang-typescript">ng g s services/gemini
</code></pre>
<p>We will use the <strong>Gemini SDK</strong> to create an instance of <strong>Google AI</strong> with the key and generate a model called <em>'gemini-pro'</em>.</p>
<p>The intended use of the model is based on a prompt. This prompt tells Gemini how to answer our questions.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { GoogleGenerativeAI } <span class="hljs-keyword">from</span> <span class="hljs-string">'@google/generative-ai'</span>;
<span class="hljs-keyword">import</span> { environment } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../environments/environment'</span>;

generativeAI = <span class="hljs-keyword">new</span> GoogleGenerativeAI(environment.gemini_key);
model = <span class="hljs-built_in">this</span>.generativeAI.getGenerativeModel({ model: <span class="hljs-string">'gemini-pro'</span> });
</code></pre>
<p>We select answers from Angular and TypeScript experts.</p>
<pre><code class="lang-typescript">  prompt = <span class="hljs-string">'You are an Angular and TypeScript expert, answer the questions providing the best examples including code'</span>
</code></pre>
<p>This is the main logic of our application and it's the way to connect with Gemini, we used a try catch to avoid errors, then we check if we have the text and start building our object for the Gemini SDK, we need to add to our model that we generated before the prompt and the question that we will get the response and in this case we just need to get the text object, we return that to use after in our component.</p>
<pre><code class="lang-typescript">  <span class="hljs-keyword">async</span> generate(textInput: <span class="hljs-built_in">string</span>) {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">if</span> (textInput) {
        <span class="hljs-keyword">const</span> parts = [{text: <span class="hljs-built_in">this</span>.prompt,},{ text: textInput }];

        <span class="hljs-keyword">const</span> modelResult = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.model.generateContent({
          contents: [{ role: <span class="hljs-string">'user'</span>, parts }],
        });
        <span class="hljs-keyword">const</span> response = modelResult.response;
        <span class="hljs-keyword">const</span> text = response.text();
        <span class="hljs-keyword">return</span> text;
      }
    } <span class="hljs-keyword">catch</span> (e: <span class="hljs-built_in">any</span>) {
      <span class="hljs-keyword">return</span> <span class="hljs-string">'An error has ocurred'</span>;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-string">'Ann error has ocurred'</span>;
  }
</code></pre>
<h2 id="heading-creating-the-chat-interface-with-nebular">Creating the chat interface with Nebular</h2>
<p>Nebular is a customizable open source Angular UI library that contains over 40 UI components.</p>
<p>It has a <a target="_blank" href="https://akveo.github.io/nebular/docs/components/chat-ui/overview#nbchatcomponent">chat component</a> with everything you need to build a chat application, it's all done so we just need to specify the information.</p>
<p>We need to import all the Nebular modules that we will use, in this case the most important ones are <strong>NbChatModule</strong> and <strong>NbLayoutModule</strong>, also we add the NbCardModule and NbSpinnerModule to add the spinner animation while we wait for the API response.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { NbCardModule, NbChatModule, NbLayoutModule, NbSpinnerModule, NbThemeModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nebular/theme'</span>;
<span class="hljs-keyword">import</span> { provideAnimations } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/platform-browser/animations'</span>;

<span class="hljs-meta">@NgModule</span>({
    ...
  imports: [
    ...
    NbChatModule,
    NbLayoutModule,
    NbCardModule,
    NbSpinnerModule
  ],
  providers: [provideAnimations()],
})
</code></pre>
<p>Don't forget to add the <strong>provideAnimations()</strong> in the providers to add the smooth animations while we are chatting.</p>
<p>Let's start with the template, we will add an nb-card to have the spinner feature while we are chatting, the <em>nb-chat</em> to see the conversation and the <em>nb-chat-form</em> to have the input message:</p>
<pre><code class="lang-typescript">&lt;nb-layout&gt;
  &lt;nb-layout-column&gt;
    &lt;nb-card [nbSpinner]=<span class="hljs-string">"isLoading"</span> nbSpinnerMessage=<span class="hljs-string">"Loading..."</span> nbSpinnerSize=<span class="hljs-string">"giant"</span> nbSpinnerStatus=<span class="hljs-string">"success"</span>&gt;
    &lt;nb-chat title=<span class="hljs-string">"Gemini chat"</span> [status]=<span class="hljs-string">"'success'"</span> size=<span class="hljs-string">"large"</span>&gt;
      <span class="hljs-meta">@for</span>( msg <span class="hljs-keyword">of</span> messages; track msg.id){
        &lt;nb-chat-message
        [<span class="hljs-keyword">type</span>]=<span class="hljs-string">"msg.type"</span>
        [message]=<span class="hljs-string">"msg.text"</span>
        [reply]=<span class="hljs-string">"msg.reply"</span>
        [sender]=<span class="hljs-string">"msg.user.name"</span>
        [date]=<span class="hljs-string">"msg.date"</span>
        [avatar]=<span class="hljs-string">"msg.user.avatar"</span>
      &gt;
    &lt;/nb-chat-message&gt;
    }
    &lt;nb-chat-form (send)=<span class="hljs-string">"sendMessage($event)"</span> [dropFiles]=<span class="hljs-string">"true"</span>&gt; &lt;/nb-chat-form&gt;
    &lt;/nb-chat&gt;
    &lt;/nb-card&gt;
  &lt;/nb-layout-column&gt;
&lt;/nb-layout&gt;
</code></pre>
<p>Let's add the logic to understand everything, we have to create the isLoading variable and the messages variable in this variable we will have our conversation, starting with the initial message.</p>
<pre><code class="lang-typescript">  isLoading = <span class="hljs-literal">false</span>;
  messages: <span class="hljs-built_in">any</span>[] = [
    {
      text: <span class="hljs-string">'Hi! I\'m Gemini, Angular and TypeScript expert, how can i help you?'</span>,
      date: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
      reply: <span class="hljs-literal">false</span>,
      user: {
        name: <span class="hljs-string">'Gemini'</span>,
        avatar: <span class="hljs-string">'https://s3.amazonaws.com/pix.iemoji.com/images/emoji/apple/ios-12/256/robot-face.png'</span>,
      },
    },
  ];
</code></pre>
<p>Do not forget to add our Gemini service</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { GeminiService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./services/gemini.service'</span>;
geminiService = inject(GeminiService);
</code></pre>
<p>Then, when the user asks a question we need to add their message to our messages array, call our gemini service and get the response, then add the new message to our array.</p>
<pre><code class="lang-typescript">  <span class="hljs-keyword">async</span> sendMessage(event: <span class="hljs-built_in">any</span>) {
    <span class="hljs-built_in">this</span>.isLoading = <span class="hljs-literal">true</span>;
    <span class="hljs-built_in">this</span>.messages.push({
      text: event.message,
      date: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
      reply: <span class="hljs-literal">true</span>,
      <span class="hljs-keyword">type</span>: <span class="hljs-string">'text'</span>,
      user: {
        name: <span class="hljs-string">'Rubén Peregrina'</span>,
        avatar: <span class="hljs-string">'https://cdn-icons-png.flaticon.com/512/5556/5556468.png'</span>,
      },
    });

    <span class="hljs-keyword">const</span> botReply = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.geminiService.generate(event.message);

    <span class="hljs-built_in">this</span>.messages.push(    {
      text: botReply,
      date: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
      reply: <span class="hljs-literal">false</span>,
      user: {
        name: <span class="hljs-string">'Gemini'</span>,
        avatar: <span class="hljs-string">'https://s3.amazonaws.com/pix.iemoji.com/images/emoji/apple/ios-12/256/robot-face.png'</span>,
      },
    },
    );
    <span class="hljs-built_in">this</span>.isLoading = <span class="hljs-literal">false</span>;
  }
</code></pre>
<p>The Nebular chat need this structure to work, the text is the message, the date is the date that will be displayed in our message, reply it's to know who is texting and finally the user, we can add the name and the avatar to display.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707130341823/e4f3dfe4-daa0-4a56-b15e-53ab32555a9e.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Finally we have our fully functional chat working with Nebular and the Gemini SDK, in this case we add a prompt to get expert answers about Angular and TypeScript.</p>
<blockquote>
<p>This is the second part of the exploring the Gemini API, you can take a look at the first part <a target="_blank" href="https://rubenperegrina.com/playing-with-googles-gemini-pro-api">here</a>.</p>
</blockquote>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🚀</div>
<div data-node-type="callout-text"><a target="_blank" href="https://github.com/rubenperegrina/gemini-chat"><strong>See the article code on GitHub</strong></a></div>
</div>

<ul>
<li><p><a target="_blank" href="https://akveo.github.io/nebular/">Nebular documentation</a></p>
</li>
<li><p><a target="_blank" href="https://deepmind.google/technologies/gemini/#introduction">Gemini documentation</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Exploring Angular 17.1's revolutionary feature: Input Signals]]></title><description><![CDATA[Angular 17.1 has recently unveiled a groundbreaking feature – Input Signals. This latest addition transforms the way we handle component inputs, replacing the familiar @Input decorator with a powerful function called input(). In this article, we'll e...]]></description><link>https://rubenperegrina.com/exploring-angular-171s-revolutionary-feature-input-signals</link><guid isPermaLink="true">https://rubenperegrina.com/exploring-angular-171s-revolutionary-feature-input-signals</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular 2]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Developer]]></category><category><![CDATA[development]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Thu, 01 Feb 2024 09:41:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/yjygDnvRuaI/upload/24677aae283c1c3040b0ba5ca83c025c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Angular 17.1</strong> has recently unveiled a groundbreaking feature – <strong>Input Signals</strong>. This latest addition transforms the way we handle component inputs, replacing the familiar <strong>@Input decorator</strong> with a powerful function called input(). In this article, we'll explore the benefits of Signal Inputs, their three distinct flavors, and how they bring a new level of flexibility and reactivity to Angular components.</p>
<p>Angular 17.1 introduces Input Signals as a developer preview, offering developers an alternative to the traditional @Input decorator. Signal Inputs provide a new approach to handling component input values, allowing for increased flexibility and reactivity.</p>
<p>The primary syntax shift comes with the introduction of the input() function from @angular/core, which creates input values received as signals. Let's look at the three available flavours of signal inputs:</p>
<h2 id="heading-default-value-signal">Default value Signal:</h2>
<p>Resolves to a Signal of a specific type.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SampleComponent {
  name = input&lt;<span class="hljs-built_in">string</span>&gt;(<span class="hljs-string">'Angular'</span>);
}
</code></pre>
<p>The <strong>'name'</strong> signal can be accessed directly, enabling dynamic updates without the need for <code>ngOnInit</code> or <code>ngOnChanges</code>.</p>
<h2 id="heading-optional-value-signal">Optional value Signal:</h2>
<p>Requires a generic type and results in a union type containing undefined.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> OptionalComponent {
  value = input&lt;<span class="hljs-built_in">number</span>&gt;(); <span class="hljs-comment">// number | undefined</span>
}
</code></pre>
<p>This allows for optional inputs, accommodating scenarios where the value may or may not be present.</p>
<h2 id="heading-required-value-signal">Required value Signal:</h2>
<p>Expects a generic type but does not include undefined in the union type.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> RequiredComponent {
  firstName = input&lt;<span class="hljs-built_in">string</span>&gt;(); <span class="hljs-comment">// string | undefined</span>
  lastName = input.required&lt;<span class="hljs-built_in">string</span>&gt;(); <span class="hljs-comment">// string</span>
}
</code></pre>
<p>The <strong>'lastName'</strong> signal ensures that a value is provided, throwing a runtime error if accessed before initialization.</p>
<blockquote>
<p>In addition, Angular 17.1 supports transformation functions for type mapping and parameter binding from the router, increasing the versatility of signal inputs.</p>
</blockquote>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Angular 17.1's Signal Inputs mark a significant evolution in the way we handle component inputs. Using the input() function, developers can embrace a more reactive and flexible approach to managing input values. The three flavors – default, optional, and required – cater to a variety of use cases, providing a seamless transition from the traditional @Input decorator. As Angular continues to innovate, Signal Inputs open up new possibilities for cleaner, more dynamic component architectures.</p>
]]></content:encoded></item><item><title><![CDATA[Angular Roadmap - The guide I wanted to have before starting in Angular]]></title><description><![CDATA[Introduction
As a beginner, it's easy to feel overwhelmed when diving into a new framework like Angular, but fear not, we're here to guide you! In this post, we'll break down a step-by-step roadmap that I wish I had when I started my Angular programm...]]></description><link>https://rubenperegrina.com/angular-roadmap-the-guide-i-wanted-to-have-before-starting-in-angular</link><guid isPermaLink="true">https://rubenperegrina.com/angular-roadmap-the-guide-i-wanted-to-have-before-starting-in-angular</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Developer]]></category><category><![CDATA[development]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[guide]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[frontend]]></category><category><![CDATA[front-end]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Mon, 22 Jan 2024 11:21:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/vv-oEGlN-4E/upload/32c238abaf9798060fb05315493e94e8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>As a beginner, it's easy to feel overwhelmed when diving into a new framework like Angular, but fear not, we're here to guide you! In this post, we'll break down a step-by-step roadmap that I wish I had when I started my Angular programming journey. Keep reading to discover essential tips, tricks, and guides that will set you apart in the world of Angular development.</p>
<p><strong>Prerequisites:</strong> Before we dive into Angular, it's essential to ensure you have a solid foundation in JavaScript. If you're not familiar with JavaScript basics, take some time to acquaint yourself with the fundamentals.</p>
<p><strong>Understanding Angular:</strong> Angular, as a robust web application framework, supports full-stack development. Its architecture is centred around <strong>TypeScript</strong> and the concept of components, which are fundamental to creating reactive single-page applications <strong>(SPAs)</strong>. Understanding these components and how they interact is key to mastering Angular.</p>
<p>By following these steps, you'll build a strong foundation in both TypeScript and Angular, setting the stage for a successful journey into the dynamic world of web development.</p>
<blockquote>
<p>Before starting, I gathered all the useful documentation links that I found and recommend checking them out.</p>
</blockquote>
<h2 id="heading-learn-typescript-basics">Learn TypeScript basics</h2>
<p>Angular is constructed with TypeScript, a strongly typed, object-oriented, and compiled programming language that extends JavaScript. To navigate the world of Angular effectively, it's crucial to grasp the basics of TypeScript. This statically typed superset of JavaScript not only enhances code reliability and maintainability but is also the backbone of Angular development.</p>
<ul>
<li><p><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/type-compatibility.html">Structural Typing</a></p>
</li>
<li><p><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/type-inference.html">Type Interface</a></p>
</li>
<li><p><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html">Union Types</a></p>
</li>
<li><p><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#built-in-types">Built-in Types</a></p>
</li>
<li><p><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#built-in-types">Type Guards</a></p>
</li>
<li><p><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/2/generics.html#handbook-content">Generics</a></p>
</li>
<li><p><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/decorators.html#handbook-content">Decorators</a></p>
</li>
<li><p><a target="_blank" href="https://rubenperegrina.com/exploring-the-essentials-typescript-utility-types">Utility Types</a></p>
</li>
</ul>
<blockquote>
<p><a target="_blank" href="https://www.typescriptlang.org/play?#code/PTAEHUFMBsGMHsC2lQBd5oBYoCoE8AHSAZVgCcBLA1UABWgEM8BzM+AVwDsATAGiwoBnUENANQAd0gAjQRVSQAUCEmYKsTKGYUAbpGF4OY0BoadYKdJMoL+gzAzIoz3UNEiPOofEVKVqAHSKymAAmkYI7NCuqGqcANag8ABmIjQUXrFOKBJMggBcISGgoAC0oACCbvCwDKgU8JkY7p7ehCTkVDQS2E6gnPCxGcwmZqDSTgzxxWWVoASMFmgYkAAeRJTInN3ymj4d-jSCeNsMq-wuoPaOltigAKoASgAywhK7SbGQZIIz5VWCFzSeCrZagNYbChbHaxUDcCjJZLfSDbExIAgUdxkUBIursJzCFJtXydajBBCcQQ0MwAUVWDEQC0gADVHBQGNJ3KAALygABEAAkYNAMOB4GRonzFBTBPB3AERcwABS0+mM9ysygc9wASmCKhwzQ8ZC8iHFzmB7BoXzcZmY7AYzEg-Fg0HUiQ58D0Ii8fLpDKZgj5SWxfPADlQAHJhAA5SASPlBFQAeS+ZHegmdWkgR1QjgUrmkeFATjNOmGWH0KAQiGhwkuNok4uiIgMHGxCyYrA4PCCJSAA">TypeScript playground</a> for practice</p>
</blockquote>
<h2 id="heading-learn-angular-cli">Learn Angular CLI</h2>
<p>The <a target="_blank" href="https://angular.dev/tools/cli">Angular CLI</a>, a command-line interface tool, streamlines the initiation, development, scaffolding, and maintenance of Angular applications directly from a command shell. To install the latest <a target="_blank" href="https://angular.dev/tools/cli">Angular CLI</a>, execute the following command:</p>
<pre><code class="lang-bash">npm install -g @angular/cli
</code></pre>
<p>Create a new project:</p>
<pre><code class="lang-bash">ng new my-app
</code></pre>
<p>One of the common commands if you need help:</p>
<pre><code class="lang-bash">ng --<span class="hljs-built_in">help</span>
ng generate --<span class="hljs-built_in">help</span>
ng build --<span class="hljs-built_in">help</span>
</code></pre>
<p>Quick guide for generating components in Angular:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Command</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td>ng g component [name] ng g c [name]</td><td>Create a new component, you can put the route also, [/path/name]</td></tr>
<tr>
<td>ng g directive [name] ng g d [name]</td><td>Create a new directive.</td></tr>
<tr>
<td>ng g guard [name] ng g g [name]</td><td>Create a new guard for routes protecting.</td></tr>
<tr>
<td>ng g interceptor [name]</td><td>Create a new interceptor.</td></tr>
<tr>
<td>ng g module [name] ng g m [name]</td><td>Create a new module, you can aggregate components inside.</td></tr>
<tr>
<td>ng g pipe [name] ng g p [name]</td><td>Create a new pipe, a data transformer.</td></tr>
<tr>
<td>ng g service [name] ng g s [name]</td><td>Create a new service, that permits sharing information in the application and making HTTP calls.</td></tr>
</tbody>
</table>
</div><p>Also, you can add flags at the ends of the command to add features, here are some examples:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Flag</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td>ng g c --help</td><td>Show the whole help for that command</td></tr>
<tr>
<td>ng g c [name] --dry-run</td><td>Run the command without changing files. Useful if you are not sure what the command will do</td></tr>
<tr>
<td>ng g c [name] --flat</td><td>Creates the new files at the specified level without creating a new new directory.</td></tr>
<tr>
<td>ng g c [name] --inline-style ng g c [name] -s</td><td>Include the styles in the same container file (.ts)</td></tr>
</tbody>
</table>
</div><blockquote>
<p>I recommend learning <a target="_blank" href="https://angular.dev/reference/configs/file-structure#library-project-files">Angular file structure</a>: How the components are organized like in modules, and their components, services, etc.</p>
</blockquote>
<h2 id="heading-lifecycle-hooks">Lifecycle Hooks</h2>
<p>A <a target="_blank" href="https://angular.dev/guide/components/lifecycle">component's lifecycle</a> in Angular begins when the component class is instantiated and the view, along with its child views, is rendered. This lifecycle includes change detection, where Angular monitors changes in data-bound properties, updating both the view and the component instance. The <a target="_blank" href="https://angular.dev/guide/components/lifecycle">lifecycle</a> concludes when Angular destroys the component instance, removing its template from the DOM. Similar to components, directives follow a lifecycle involving creation, updates, and destruction during execution.</p>
<p>To interact with these lifecycles, your application can utilize <a target="_blank" href="https://angular.dev/guide/components/lifecycle">lifecycle hook</a> methods, which allow you to handle key events such as initialization, change detection, response to updates, and cleanup before deletion. The essential <a target="_blank" href="https://angular.dev/guide/components/lifecycle">Angular lifecycle hooks</a> are:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>OnChanges</strong></td><td>Called when the input properties have changed</td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://angular.dev/guide/components/lifecycle#ngoninit"><strong>OnInit</strong></a></td><td>Called on initialization</td></tr>
<tr>
<td><a target="_blank" href="https://angular.dev/guide/components/lifecycle#ngdocheck"><strong>DoCheck</strong></a></td><td>Developer’s custom change detection</td></tr>
<tr>
<td><a target="_blank" href="https://angular.dev/guide/components/lifecycle#ngondestroy"><strong>OnDestroy</strong></a></td><td>Called before the component is destroyed</td></tr>
<tr>
<td><a target="_blank" href="https://angular.dev/guide/components/lifecycle#ngaftercontentinit"><strong>AfterContentInit</strong></a></td><td>Called when the component’s content <code>ngContent</code> is initialized</td></tr>
<tr>
<td><a target="_blank" href="https://angular.dev/guide/components/lifecycle#ngaftercontentchecked"><strong>AfterContentChecked</strong></a></td><td>Called when the component’s content is updated or checked for updates</td></tr>
<tr>
<td><a target="_blank" href="https://angular.dev/guide/components/lifecycle#ngafterviewinit"><strong>AfterViewInit</strong></a></td><td>Called when the component’s projected view has been initialized</td></tr>
<tr>
<td><a target="_blank" href="https://angular.dev/guide/components/lifecycle#ngafterviewchecked"><strong>AfterViewChecked</strong></a></td><td>Called after the projected view has been checked</td></tr>
</tbody>
</table>
</div><blockquote>
<p>See more about the Angular's lifecycle hooks <a target="_blank" href="https://angular.dev/guide/components/lifecycle">here</a></p>
</blockquote>
<h2 id="heading-templates">Templates</h2>
<p>A component, comprising a TypeScript class, an HTML template, and a CSS style sheet, governs a designated area of the screen known as a view. The TypeScript class orchestrates the interaction between the <a target="_blank" href="https://angular.dev/guide/templates">HTML template</a> and the resulting DOM structure, while the style sheet dictates the component's appearance.</p>
<p>In an Angular application, distinct components are employed to define and manage various facets of the application, there are a few things that you need to know before continuing:</p>
<ul>
<li><p><strong>Interpolation</strong>: Involves <a target="_blank" href="https://angular.dev/guide/templates/interpolation">embedding expressions</a> into marked-up text using double curly braces {{ }} as delimiters. Angular then substitutes <code>currentCustomer</code> with the string value of the corresponding component property.</p>
</li>
<li><p><strong>Property binding</strong>: Enables the assignment of values to properties of HTML elements or directives. By <a target="_blank" href="https://angular.dev/guide/templates/property-binding">enclosing the element's property in square brackets</a> [], Angular interprets the right-hand side of the assignment as a dynamic expression.</p>
</li>
<li><p><strong>Template statements:</strong> Are employed in HTML to respond to user events, facilitating actions like <a target="_blank" href="https://angular.dev/guide/templates/template-statements">displaying dynamic content</a> or submitting forms. By enclosing the event in (), Angular evaluates the right-hand side of the assignment as one or more template statements linked together with semicolons (;).</p>
</li>
<li><p><strong>Binding(data, props, attrs, events):</strong> In Angular templates, <a target="_blank" href="https://angular.dev/guide/templates/binding">bindings</a> establish a dynamic link between the view and the model, ensuring synchronization.</p>
<ul>
<li><p><a target="_blank" href="https://angular.dev/guide/templates/property-binding"><strong>Property Binding</strong></a><strong>:</strong> Sets values for properties of HTML elements or directives.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/templates/attribute-binding"><strong>Attribute Binding</strong></a><strong>:</strong> Directly sets values for attributes of HTML elements.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/templates/event-binding"><strong>Event Binding</strong></a><strong>:</strong> Listens for and responds to user actions, like keystrokes, mouse movements, clicks, and touches.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/templates/two-way-binding"><strong>Two-Way Data Binding</strong></a><strong>:</strong> Combines property and event binding, facilitating data sharing between components.</p>
</li>
</ul>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/templates/reference-variables"><strong>Reference variables</strong></a><strong>:</strong> Enable the utilization of data from one section of a template in another. These variables can reference a DOM element within a template, component, or directive. To declare a template reference variable, employ the hash symbol, #, in the template.</p>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/templates/two-way-binding">@Input() @Output()</a>: facilitate communication between a child and its parent component in Angular. With <code>@Input()</code>, a parent component can update data in the child component, while <code>@Output()</code> allows the child to send data to the parent component.</p>
</li>
</ul>
<p>Some examples:</p>
<pre><code class="lang-xml">// Render the title propertu
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ title }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
// Render the image with the url property
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"item"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ itemImageUrl }}"</span>&gt;</span>
// Call deleteHero function when click button
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"deleteHero()"</span>&gt;</span>Delete hero<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
// Call the function onSubmit with form parameteres
<span class="hljs-tag">&lt;<span class="hljs-name">form</span> #<span class="hljs-attr">heroForm</span> (<span class="hljs-attr">ngSubmit</span>)=<span class="hljs-string">"onSubmit(heroForm)"</span>&gt;</span> ... <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
// Disabled o enabled button by condition isUnchanged
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> [<span class="hljs-attr">disabled</span>]=<span class="hljs-string">"isUnchanged"</span>&gt;</span>Disabled Button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
// Shareing data between child and parent component
<span class="hljs-tag">&lt;<span class="hljs-name">app-item-detail</span> [<span class="hljs-attr">childItem</span>]=<span class="hljs-string">"parentItem"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">app-item-detail</span>&gt;</span>
// Two way data binding between child and parent component
<span class="hljs-tag">&lt;<span class="hljs-name">app-sizer</span> [(<span class="hljs-attr">size</span>)]=<span class="hljs-string">"fontSizePx"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">app-sizer</span>&gt;</span>
</code></pre>
<blockquote>
<p>Take it easy to understand all of the concepts, I know the first impression could be difficult. <a target="_blank" href="https://angular.dev/guide/templates">This documentation maybe could be useful</a></p>
</blockquote>
<h2 id="heading-routing">Routing</h2>
<p><a target="_blank" href="https://angular.dev/guide/routing">Angular's routing</a> empowers users to construct a single-page application featuring multiple views and seamless navigation between them. This enables users to switch between views without sacrificing the application state and properties.</p>
<p>Here is a short example of how can <a target="_blank" href="https://angular.dev/guide/routing/router-reference">configure routes</a>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> routes: Routes = [
    { path: <span class="hljs-string">'home'</span>, component: HomeComponent },
    { path: <span class="hljs-string">'detail/:id'</span>, component: ... },
    { path: <span class="hljs-string">'about'</span>, component: ... },
    { path: <span class="hljs-string">'items'</span>, <span class="hljs-comment">// lazy load a module</span>
    loadChildren: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./items/
    items.module'</span>).then(<span class="hljs-function"><span class="hljs-params">m</span> =&gt;</span> m.ItemsModule)}
]);
</code></pre>
<p>We need to put the <a target="_blank" href="https://angular.dev/guide/routing/router-reference">router-outlet</a> element in the HTML to say Angular where we want to render our routes:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">router-outlet</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-outlet</span>&gt;</span>
</code></pre>
<p>We use the control navidation to <a target="_blank" href="https://angular.dev/guide/routing/router-reference">link our routes</a> inside of our app like this:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">routerLink</span>=<span class="hljs-string">"/home"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">a</span> [<span class="hljs-attr">routerLink</span>]=<span class="hljs-string">"[ '/detail', user.id]”&gt;</span></span>
</code></pre>
<h1 id="heading-learn-the-basics-of-rxjs">Learn the basics of RxJS</h1>
<p><a target="_blank" href="https://rxjs.dev/">RxJS</a> is a reactive library used to implement reactive programming to deal with async implementation, callbacks, and event-based programs.</p>
<ul>
<li><p><a target="_blank" href="https://rxjs.dev/api/index/interface/Observer"><strong>Observer Pattern</strong></a>: The observer pattern is a software design approach where a subject object keeps a list of dependents (observers) and automatically informs them of any state changes by calling one of their methods. In Angular, this pattern is employed through Observables, where objects subscribe to them using the <code>subscribe</code> method and respond when the observable undergoes any relevant action.</p>
</li>
<li><p><a target="_blank" href="https://rxjs.dev/api/index/interface/Observer"><strong>Observable lifecycle</strong></a><strong>:</strong> An observable, functioning as a wrapper for a data stream, enables message passing within your application. However, it becomes meaningful only when an observer subscribes to it. The observer, consuming data emitted by the observable, continues to receive values until either the observable completes or the observer unsubscribes. This asynchronous process allows for diverse operations like updating the user interface or handling JSON responses.</p>
<p>  The observable life cycle consists of four stages: creation, subscription, execution, and destruction.</p>
</li>
<li><p><a target="_blank" href="https://rxjs.dev/deprecations/to-promise"><strong>RxJS vs Promises</strong></a><strong>:</strong> Eager vs. Lazy, Asynchronous Nature, Data Delivery.</p>
</li>
</ul>
<h1 id="heading-learn-how-to-use-rxjs-operators">Learn how to use RxJS operators</h1>
<p><strong>RxJS</strong> is primarily valued for its <a target="_blank" href="https://rxjs.dev/guide/operators">operators</a>, which, while built on the foundation of Observables, play a pivotal role. These <a target="_blank" href="https://rxjs.dev/guide/operators">operators</a> serve as crucial components, enabling the seamless composition of intricate asynchronous code in a declarative fashion.</p>
<p><strong>There are two kinds of operators:</strong></p>
<p><strong>Pipeable Operators</strong>, like <code>filter(…)</code> and <code>mergeMap(…)</code>, can be applied to <strong>Observables</strong> using the syntax <code>observableInstance.pipe(operator())</code>. These operators do <strong>not alter the existing Observable</strong> instance; instead, they <strong>create a new Observable</strong>. Subscribing to the new <strong>Observable</strong> also subscribes to the original one.</p>
<p>Piping involves chaining these operators together, enhancing readability. The <code>.pipe()</code> method of <strong>Observables</strong> achieves this concisely:</p>
<pre><code class="lang-typescript">codeobs.pipe(op1(), op2(), op3(), op4());
</code></pre>
<p><strong>Creation Operators</strong> are standalone functions used to <strong>create new Observables</strong> with predefined behaviors or by <strong>combining other Observables</strong>. For example, the interval function takes a number as an input argument and produces an Observable:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> observable = interval(<span class="hljs-number">1000</span>);
</code></pre>
<p>These operators are distinct from pipeable operators and will be explored in more detail in a later section.</p>
<h2 id="heading-are-there-more">Are there more?</h2>
<p>Yes, this is only the basics, with this you are ready to create your first Angular application, create some components, link to a routes and render some information, but this is just the beginning, Angular has a lot more, here are a few more concepts that you need to know to take all the Angular advantages:</p>
<ul>
<li><p><a target="_blank" href="https://angular.dev/guide/forms"><strong>Forms</strong></a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/pipes"><strong>Pipes</strong></a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/directives"><strong>Directives</strong></a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/api/router/CanActivate"><strong>Guards</strong></a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/http/interceptors#configuring-interceptors"><strong>Interceptors</strong></a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/api/router/Resolve#"><strong>Resolvers</strong></a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/api/common/http/HttpClient"><strong>HttpClient</strong></a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/testing"><strong>Testing</strong></a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/signals"><strong>Signals</strong></a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/guide/defer"><strong>Deferrable Views</strong></a></p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Maybe from the outside Angular looks like another framework, but in my opinion, it's not it. Angular it's a platform more than a framework, it's a platform that offers you all the necessary things to build great quality applications, most of the time you don't need to install third-party libraries to do some things, Angular has many features like SRR, PWA, great forms, good security etc.</p>
<p>Many themes have remained to talk about in this article, maybe I can write another article with more foundation, let me know in the comments.</p>
<h2 id="heading-information-that-may-interest-you">Information that may interest you</h2>
<ul>
<li><p><a target="_blank" href="https://rubenperegrina.com/series/angular">https://rubenperegrina.com/series/angular</a></p>
</li>
<li><p><a target="_blank" href="https://angular.io/docs">https://angular.io/docs</a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/overview">https://angular.dev/overview</a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/tutorials/learn-angular">https://angular.dev/tutorials/learn-angular</a></p>
</li>
<li><p><a target="_blank" href="https://angular.dev/tutorials/first-app">https://angular.dev/tutorials/first-app</a></p>
</li>
<li><p><a target="_blank" href="https://roadmap.sh/angular">https://roadmap.sh/angular</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Use aliases for your imports]]></title><description><![CDATA[In TypeScript projects, especially in Angular, it's easy to have too many files and too many imports in our components. This leads to confusion and errors when importing. In this post we have a quick guide to avoid this.
We've all seen this type of i...]]></description><link>https://rubenperegrina.com/use-aliases-for-your-imports</link><guid isPermaLink="true">https://rubenperegrina.com/use-aliases-for-your-imports</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Wed, 10 Jan 2024 11:48:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/kyCNGGKCvyw/upload/3ba3a476f3bfbf622e7674387423d1a3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In <strong>TypeScript</strong> projects, especially in <strong>Angular</strong>, it's easy to have too many files and too many imports in our components. This leads to confusion and errors when importing. In this post we have a quick guide to avoid this.</p>
<p>We've all seen this type of import in our files:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Something } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../../../../../../something.ts'</span>;
</code></pre>
<p>You can work around this by using aliases in the <code>tsconfig.json</code> attribute via paths:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// tsconfig.json</span>
{
  <span class="hljs-string">"compilerOptions"</span>: {
    ...
    <span class="hljs-string">"paths"</span>: {
      <span class="hljs-string">"@components/*"</span>: [<span class="hljs-string">"src/app/components/*"</span>],
      <span class="hljs-string">"@routes/*"</span>: [<span class="hljs-string">"src/app/routes/*"</span>],
      <span class="hljs-string">"@shared/*"</span>: [<span class="hljs-string">"src/app/shared/*"</span>],       
    }
  }
}
</code></pre>
<p>You can then use these aliases to import your resources:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { ButtonComponent, CardComponent } <span class="hljs-keyword">from</span> <span class="hljs-string">'@components'</span>;
<span class="hljs-keyword">import</span> { formatText } <span class="hljs-keyword">from</span> <span class="hljs-string">'@shared/utils/formatting'</span>;
<span class="hljs-keyword">import</span> { converting } <span class="hljs-keyword">from</span> <span class="hljs-string">'@shared/utils/converting'</span>;
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You should do this for several reasons:</p>
<ul>
<li><p>It is much easier to read than relative paths.</p>
</li>
<li><p>This is useful for refactoring: if your code changes location, the import stays the same.</p>
</li>
<li><p>IDEs can import directly from aliases</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Read URL route parameters using Angular @input]]></title><description><![CDATA[Since Angular 16 we can change the way parameters from URL work, until version 16 comes out we have done this with an activatedRoute, let's take a look at one of the cool features in this version.

🚀
See the article code on GitHub


How was it done ...]]></description><link>https://rubenperegrina.com/read-url-route-parameters-using-angular-input</link><guid isPermaLink="true">https://rubenperegrina.com/read-url-route-parameters-using-angular-input</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Thu, 21 Dec 2023 10:20:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/MAYEkmn7G6E/upload/64f76461a1ce24b5949837b4789cfab0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Since Angular 16 we can change the way parameters from URL work, until version 16 comes out we have done this with an <code>activatedRoute</code>, let's take a look at one of the cool features in this version.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🚀</div>
<div data-node-type="callout-text"><a target="_blank" href="https://github.com/rubenperegrina/input-url-parameter">See the article code on GitHub</a></div>
</div>

<h2 id="heading-how-was-it-done-before">How was it done before?</h2>
<p>Once we have configured our route file with the parameters we want to pass to each of the URLs, we need to get those parameters into the component.</p>
<p><strong>Let's look at an example:</strong></p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { ActivatedRoute } <span class="hljs-keyword">from</span> <span class="hljs-string">"@angular/router"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UserComponent <span class="hljs-keyword">implements</span> OnInit {
  activatedRoute = inject(ActivatedRoute);
  ngOnInit(): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">let</span> paramId = <span class="hljs-built_in">this</span>.activatedRoute.snapshot.paramMap.get(<span class="hljs-string">'id'</span>);
  }
}
</code></pre>
<p>As you can see, first we need to import and inject the ActivatedRoute to use it, and then we need to obtain the param from ActivatedRoute, in this example the param calls <code>id</code></p>
<h2 id="heading-how-is-it-done-now">How is it done now?</h2>
<p>First of all, we need to add the route with the parameter that we need to send, this step is the same in the older way and in the new way.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> routes: Routes = [
    {
        path: <span class="hljs-string">'user/:id'</span>,
        loadComponent: <span class="hljs-function">() =&gt;</span>
            <span class="hljs-keyword">import</span>(<span class="hljs-string">'./user/user.component'</span>).then(<span class="hljs-function"><span class="hljs-params">c</span> =&gt;</span> c.UserComponent)
    }
];
</code></pre>
<p>For this example, we created a UserComponent and added an <code>id</code> in the URL.</p>
<p>To obtain parameters through URL using inputs we need to import the <code>withComponentInputBinding()</code> in our <code>app.config.ts</code></p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { withComponentInputBinding } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> appConfig: ApplicationConfig = {
  providers: [provideRouter(routes, withComponentInputBinding())]
};
</code></pre>
<p>Just import the <code>withComponentInputBinding</code> from angular/core and add to the providers, now Angular knows that we want to use input properties to read route parameters.</p>
<blockquote>
<p>If you are still using modules in your application set <code>bindToComponentInputs</code> to true in your <code>AppRoutingModule</code></p>
</blockquote>
<p>In our component just need to add an input with the name of our parameter like this:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@Input</span>() id!: <span class="hljs-built_in">string</span>;
</code></pre>
<p>If we need to change the name and don't use the same parameter name we can rename the input like this:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@Input</span>(<span class="hljs-string">'id'</span>) paramId!: <span class="hljs-built_in">string</span>;
</code></pre>
<p>Now we can obtain our parameter in the <code>ngOnInit</code> function without using the <code>activatedRoute</code>, we just need to use our variable from the input</p>
<pre><code class="lang-typescript">  ngOnInit(): <span class="hljs-built_in">void</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>.id);
  }
</code></pre>
<p>Using the new way we don't need to import and inject the <code>activatedRoute</code> and we write less code.</p>
<p>Angular automatically reads the route parameter and assigns it to the input property.</p>
<blockquote>
<p>Remember that if you want to access the value of the parameter in the constructor, it will be empty, you need to access it in the ngOnInit.</p>
</blockquote>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article we have discovered a simple way to collect parameters from the URL, saving us code in a very simple way, I think that from now on we will leave behind the <code>activatedRoute</code> to do it this way.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🚀</div>
<div data-node-type="callout-text"><a target="_blank" href="https://github.com/rubenperegrina/input-url-parameter">See the article code on GitHub</a></div>
</div>]]></content:encoded></item><item><title><![CDATA[Playing with Google's Gemini Pro API]]></title><description><![CDATA[Last week, Google announced its own biggest and most powerful AI, which was a bit controversial because it was announced with comparisons against OpenAI's ChatGPT, in most of the comparisons Google's AI came out on top.
After a year with ChatGPT amon...]]></description><link>https://rubenperegrina.com/playing-with-googles-gemini-pro-api</link><guid isPermaLink="true">https://rubenperegrina.com/playing-with-googles-gemini-pro-api</guid><category><![CDATA[AI]]></category><category><![CDATA[Google]]></category><category><![CDATA[chatgpt]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[#PromptEngineering]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[gemini]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Thu, 14 Dec 2023 15:29:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/NnYbRvZUi9A/upload/af5524f180b07054d6597f2f7398c75a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last week, <strong>Google announced its own biggest and most powerful AI</strong>, which was a bit controversial because it was announced with comparisons against <strong>OpenAI's ChatGPT</strong>, in most of the comparisons Google's AI came out on top.</p>
<p>After a year with ChatGPT among us, it seems that the first real competition is coming out.</p>
<p>Not only have they presented Gemini, as it's called, but from day one they've opened up the API to use it, they've provided a <strong>free API key for development purposes</strong>, which is great!</p>
<p>In this article, we are going to test the capabilities of Gemini using its API.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🚀</div>
<div data-node-type="callout-text"><a target="_blank" href="https://github.com/rubenperegrina/google-gemini-pro-ai">See the article code on GitHub</a></div>
</div>

<h2 id="heading-how-to-get-the-api-key">How to get the API key?</h2>
<p>Go to <a target="_blank" href="https://ai.google.dev/">https://ai.google.dev/</a> and obtain your API key</p>
<p>Once we have the key we need to create a project to use it, in this case, we are going to use <a target="_blank" href="https://rubenperegrina.com/whats-new-in-angular-17">Angular</a>.</p>
<h2 id="heading-creating-our-gemini-project">Creating our Gemini project</h2>
<p>First, we will create our project to be able to use <strong>Gemini</strong>, I assume you have everything you need to work with Angular installed, if not you can see it here:</p>
<p><a target="_blank" href="https://angular.dev/tutorials/first-app">https://angular.dev/tutorials/first-app</a></p>
<p>We will create our project using Angular CLI:</p>
<pre><code class="lang-typescript">ng n google-gemini-pro-ai
</code></pre>
<h2 id="heading-installing-gemini-library">Installing Gemini library</h2>
<p>Install the <strong>Google Gemini library</strong> with the following command:</p>
<pre><code class="lang-typescript">npm i <span class="hljs-meta">@google</span>/generative-ai
</code></pre>
<p>Make sure everything goes well and check your package.json to see if the <strong>@google/generative-ai</strong> is installed.</p>
<h2 id="heading-using-the-gemini-api">Using the Gemini API</h2>
<p>The last and most important part, inside our component where we will display the results, we create a new <code>GoogleGenerativeAI</code>, is imported from the library we have installed.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { GoogleGenerativeAI } <span class="hljs-keyword">from</span> <span class="hljs-string">'@google/generative-ai'</span>;
<span class="hljs-keyword">import</span> { environment } <span class="hljs-keyword">from</span> <span class="hljs-string">'../environments/environment'</span>;
generativeAI = <span class="hljs-keyword">new</span> GoogleGenerativeAI(environment.gemini_api_key);
</code></pre>
<p><code>GoogleGenerativeAI</code> gets the API key, in this case, we have set it in the environments.</p>
<blockquote>
<p>You can generate your own environments with ng g environments</p>
</blockquote>
<p>Then we have to choose the model we are going to use, we choose it by calling <code>getGenerativeModel</code> on our <code>GoogleGenerativeAI</code> that we have generated before, I expect to get a model, so we choose <strong>gemini-pro.</strong></p>
<pre><code class="lang-typescript">model = <span class="hljs-built_in">this</span>.generativeAI.getGenerativeModel({ model: <span class="hljs-string">'gemini-pro'</span> });
</code></pre>
<p>In this example I have added an input so that the user can add their prompt, the result will be displayed on the screen.</p>
<pre><code class="lang-typescript">  &lt;h1&gt; Google Gemini pro &lt;/h1&gt;
  &lt;label <span class="hljs-keyword">for</span>=<span class="hljs-string">"prompt"</span>&gt;Type your prompt&lt;/label&gt;
  &lt;br&gt;&lt;br&gt;
  &lt;input id=<span class="hljs-string">"prompt"</span> [(ngModel)]=<span class="hljs-string">"prompt"</span> placeholder=<span class="hljs-string">"Enter your prompt here"</span> /&gt;
  &lt;button (click)=<span class="hljs-string">"generate()"</span> [disabled]=<span class="hljs-string">"!prompt"</span>&gt;Generate!&lt;/button&gt;
  &lt;br&gt;&lt;br&gt;
  <span class="hljs-meta">@defer</span> (when result) {
    {{ result }}
  }
  <span class="hljs-meta">@placeholder</span> {
    &lt;span&gt;Waiting <span class="hljs-keyword">for</span> your prompt&lt;/span&gt;
  }
  <span class="hljs-meta">@loading</span>(minimum <span class="hljs-number">1</span>s) {
    &lt;span&gt;Loading...&lt;/span&gt;
  }
</code></pre>
<p>When the user adds the prompt and clicks the generate button, it calls the function that calls the Gemini API.</p>
<pre><code class="lang-typescript">  <span class="hljs-keyword">async</span> generate() {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.model.generateContent(<span class="hljs-built_in">this</span>.prompt);
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> result.response;
      <span class="hljs-built_in">this</span>.result = response.text();
    } <span class="hljs-keyword">catch</span>(e: <span class="hljs-built_in">any</span>) {
      <span class="hljs-built_in">this</span>.result = e;
    }
  }
</code></pre>
<p>Simply with our model created, we need to call <code>generateContent</code> passing the user prompt, it will return the result or an error, we control this with the <a target="_blank" href="https://rubenperegrina.com/how-does-angulars-new-control-flow-work">new defer blocks</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>That's all, with just a few lines we can start using the Gemini Pro API, this is a simple example where we have just used text with a simple answer, in the following articles I will make examples with <strong>data stream to make a chat, answers with images and everything that this API allows us to do</strong>.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🚀</div>
<div data-node-type="callout-text"><a target="_blank" href="https://github.com/rubenperegrina/google-gemini-pro-ai">See the article code on GitHub</a></div>
</div>]]></content:encoded></item><item><title><![CDATA[State management in Angular, what options are there?]]></title><description><![CDATA[Managing information in our application can be challenging, especially in terms of developer experience, knowledge, and security.
Nearly all mid to large-sized applications require data management to ensure accessibility across all pages, with featur...]]></description><link>https://rubenperegrina.com/state-management-in-angular-what-options-are-there</link><guid isPermaLink="true">https://rubenperegrina.com/state-management-in-angular-what-options-are-there</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[State Management ]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Wed, 13 Dec 2023 19:10:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/5e2KVwyojpc/upload/0be23ed860025cef5afed8940f97601a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Managing information in our application can be challenging, especially in terms of developer experience, knowledge, and security.</p>
<p>Nearly all mid to large-sized applications require data management to ensure accessibility across all pages, with features for reading, adding, and editing.</p>
<p>Angular, being a robust framework, offers tools and libraries for streamlined state management. In this post, we will explore well-known state management solutions, customized to suit particular requirements in Angular applications.</p>
<h2 id="heading-1-stateful-services-subjects">1. Stateful Services (Subjects)</h2>
<p>Using the power of Subjects, <strong>Stateful Services</strong> provide a simple way to manage state within Angular. By exploring this way, developers can easily manage the state of the application just using <strong>RxJS</strong>, you don't need to install any third-party libraries and easily to use but has some limitations instances others.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-typescript"><span class="hljs-meta">@Injectable</span>({
  providedIn: <span class="hljs-string">'root'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> StatefulService {
  <span class="hljs-keyword">private</span> stateSubject = <span class="hljs-keyword">new</span> Subject&lt;<span class="hljs-built_in">string</span>&gt;();
  state$ = <span class="hljs-built_in">this</span>.stateSubject.asObservable();

  updateState(newState: <span class="hljs-built_in">string</span>) {
    <span class="hljs-built_in">this</span>.stateSubject.next(newState);
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> MyComponent <span class="hljs-keyword">implements</span> OnInit {
  currentState: <span class="hljs-built_in">string</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> statefulService: StatefulService</span>) {}

  ngOnInit() {
    <span class="hljs-built_in">this</span>.statefulService.state$.subscribe(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
      <span class="hljs-built_in">this</span>.currentState = state;
    });
  }

  updateState() {
    <span class="hljs-built_in">this</span>.statefulService.updateState(<span class="hljs-string">'New State'</span>);
  }
}
</code></pre>
<h2 id="heading-2-ngrx">2. NgRx</h2>
<p>NgRx Global Store is a robust state management solution inspired by <strong>Redux</strong>. It centralizes state and actions, providing a predictable and scalable approach to managing application data.</p>
<p>We can use it globally in our application or manage every single component or module with them.</p>
<blockquote>
<p>If you are using Signals in your application you can use NgRx SIgnals Store for better performance.</p>
</blockquote>
<p><strong>Example:</strong></p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Actions</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> updateMessage = createAction(<span class="hljs-string">'[App] Update Message'</span>, props&lt;{ message: <span class="hljs-built_in">string</span> }&gt;());

<span class="hljs-comment">// Reducer</span>
<span class="hljs-keyword">const</span> initialState = { message: <span class="hljs-string">''</span> };
<span class="hljs-keyword">const</span> appReducer = createReducer(
  initialState,
  on(updateMessage, <span class="hljs-function">(<span class="hljs-params">state, { message }</span>) =&gt;</span> ({ ...state, message }))
);

<span class="hljs-comment">// Store</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> appStore = createFeatureSelector(<span class="hljs-string">'app'</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> selectMessage = createSelector(appStore, <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.message);

<span class="hljs-comment">// Component</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> MyComponent {
  message$ = <span class="hljs-built_in">this</span>.store.pipe(select(selectMessage));

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> store: Store</span>) {}

  updateMessage() {
    <span class="hljs-built_in">this</span>.store.dispatch(updateMessage({ message: <span class="hljs-string">'New Message'</span> }));
  }
}
</code></pre>
<h2 id="heading-3-ngxs">3. NGXS</h2>
<p>NGXS is a state management library that simplifies complex state management scenarios. It combines the simplicity of <strong>Redux with Angular's reactive approach</strong>, providing a convenient solution for developers.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// State</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> AppStateModel {
  message: <span class="hljs-built_in">string</span>;
}

<span class="hljs-meta">@State</span>&lt;AppStateModel&gt;({
  name: <span class="hljs-string">'app'</span>,
  defaults: { message: <span class="hljs-string">''</span> },
})
<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppState {
  <span class="hljs-meta">@Selector</span>()
  <span class="hljs-keyword">static</span> getMessage(state: AppStateModel) {
    <span class="hljs-keyword">return</span> state.message;
  }

  <span class="hljs-meta">@Action</span>(UpdateMessage)
  updateMessage({ patchState }: StateContext&lt;AppStateModel&gt;, { message }: UpdateMessage) {
    patchState({ message });
  }
}

<span class="hljs-comment">// Action</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UpdateMessage {
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">type</span> = <span class="hljs-string">'[App] Update Message'</span>;
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">public</span> message: <span class="hljs-built_in">string</span></span>) {}
}

<span class="hljs-comment">// Component</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> MyComponent {
  message$ = <span class="hljs-built_in">this</span>.store.select(AppState.getMessage);

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> store: Store</span>) {}

  updateMessage() {
    <span class="hljs-built_in">this</span>.store.dispatch(<span class="hljs-keyword">new</span> UpdateMessage(<span class="hljs-string">'New Message'</span>));
  }
}
</code></pre>
<p>This example uses NGXS to define a simple state with a message. It also includes an action to update the message and a selector to access the message from the component. Remember to install and configure NGXS in your application before using this code.</p>
<p><strong>There are more options like:</strong><br />- State adapt<br />- RxAngular<br />- MiniRx<br />- Ngx Signal State<br />- Akita<br />- Elf<br />- Custom state management</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Choosing the appropriate state management option for your Angular app relies on the needs of your project. Whether you prefer the easy Stateful Services or the adaptable <strong>NgRx</strong>, grasping these tools helps Angular developers create strong and sustainable applications.</p>
<p>This article gives a quick introduction to state management options in the Angular ecosystem. Try out these tools, analyze their benefits, and select the one that fits your project's requirements best.</p>
<p><a target="_blank" href="https://rubenperegrina.com/vscode-snippets-for-ngrx">VSCode snippets for NgRx</a></p>
]]></content:encoded></item><item><title><![CDATA[5 Angular best practices for robust development]]></title><description><![CDATA[Angular is a robust framework developed by Google that allows developers to build dynamic single page applications based on TypeScript. As we delve into the intricate world of Angular development, it's crucial to navigate with precision and expertise...]]></description><link>https://rubenperegrina.com/5-angular-best-practices-for-robust-development</link><guid isPermaLink="true">https://rubenperegrina.com/5-angular-best-practices-for-robust-development</guid><category><![CDATA[Angular]]></category><category><![CDATA[Angular]]></category><category><![CDATA[performance]]></category><category><![CDATA[best practices]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Rubén Peregrina]]></dc:creator><pubDate>Fri, 08 Dec 2023 19:22:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/hbnH0ILjUZE/upload/d2a129d3874064e4d8392c50eb76a0a9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Angular</strong> is a robust framework developed by <strong>Google</strong> that allows developers to build dynamic single page applications based on TypeScript. As we delve into the intricate world of Angular development, it's crucial to navigate with precision and expertise. In this article, we'll explore <strong>five advanced strategies</strong> that go beyond the basics and unlock the full potential of Angular for seamless and superior development.</p>
<h2 id="heading-increase-efficiency-with-angular-cli">Increase efficiency with Angular CLI</h2>
<ul>
<li><p>Angular CLI is essential for project <strong>creation and management</strong></p>
</li>
<li><p>It provides a standardized, efficient way to bootstrap, develop, test, and deploy Angular applications.</p>
</li>
</ul>
<p>Here are a few examples:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Generate a new service</span>
ng generate service my-service
<span class="hljs-comment"># Run unit tests</span>
ng <span class="hljs-built_in">test</span>
<span class="hljs-comment"># Build the application for production</span>
ng build --prod
<span class="hljs-comment"># Add a dependency (e.g., Angular Material)</span>
ng add @angular/material
<span class="hljs-comment"># Update Angular CLI to the latest version</span>
ng update @angular/cli
<span class="hljs-comment"># Add Angular Routing to the project</span>
ng generate module app-routing --flat --module=app
<span class="hljs-comment"># Serve the application on a different port</span>
ng serve --port 4201
<span class="hljs-comment"># Create a production build with AOT compilation</span>
ng build --prod --aot
<span class="hljs-comment"># Run end-to-end (e2e) tests</span>
ng e2e
</code></pre>
<h2 id="heading-build-maintainable-code-by-aplying-single-responsibility-principle">Build maintainable code by aplying single responsibility principle</h2>
<ul>
<li><p>Each component, service, or module should have a <strong>single responsibility</strong></p>
</li>
<li><p>The single responsibility principle promotes <strong>maintainability, readability, and reusability</strong>, ensuring an understandable and debuggable code base.</p>
</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component, Input } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-user'</span>,
  template: <span class="hljs-string">`
    &lt;div&gt;
      &lt;h2&gt;User Details&lt;/h2&gt;
      &lt;p&gt;Name: {{ user.name }}&lt;/p&gt;
      &lt;p&gt;Email: {{ user.email }}&lt;/p&gt;
    &lt;/div&gt;
  `</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UserComponent {
  <span class="hljs-meta">@Input</span>() user: UserInfo;
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> UserInfo {
  name: <span class="hljs-built_in">string</span>;
  email: <span class="hljs-built_in">string</span>;
}
</code></pre>
<h2 id="heading-improve-the-performance-with-onpush-change-detection">Improve the performance with OnPush change detection</h2>
<ul>
<li><p>Use <strong>ChangeDetectionStrategy.OnPush</strong> to optimize component change detection.</p>
</li>
<li><p>OnPush reduces the number of checks, significantly improving performance, especially in larger applications.</p>
</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component, ChangeDetectionStrategy } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-user'</span>,
  template: <span class="hljs-string">'&lt;div&gt;{{ user.name }}&lt;/div&gt;'</span>,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UserComponent {
  user = { name: <span class="hljs-string">'Rubén Peregrina'</span> };
}
</code></pre>
<h2 id="heading-implement-smart-component-architecture">Implement Smart Component Architecture</h2>
<ul>
<li><p>Use an intelligent component architecture for <strong>improved maintainability</strong> and scalability.</p>
</li>
<li><p>This architecture <strong>improves code organization</strong>, making it easier to understand and debug.</p>
</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-user-container'</span>,
  template: <span class="hljs-string">`
    &lt;h2&gt;User Management&lt;/h2&gt;
    &lt;app-user-details [selectedUser]="selectedUser"&gt;&lt;/app-user-details&gt;
  `</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UserContainerComponent{
  selectedUser: User = [name: <span class="hljs-string">'Rubén'</span>, email: <span class="hljs-string">'ruben@hashnode.com'</span>];
}
</code></pre>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Component, Input } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-user-details'</span>,
  template: <span class="hljs-string">`
    @if (selectedUser){
      &lt;h3&gt;User Details&lt;/h3&gt;
      &lt;p&gt;Name: {{ selectedUser.name }}&lt;/p&gt;
      &lt;p&gt;Email: {{ selectedUser.email }}&lt;/p&gt;
    }
  `</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UserDetailsComponent {
  <span class="hljs-meta">@Input</span>() selectedUser: UserInfo;
}
</code></pre>
<h2 id="heading-lazy-loading-for-improved-performance">Lazy loading for improved performance</h2>
<ul>
<li><p>Implement lazy loading for feature modules to load them on demand.</p>
</li>
<li><p>Lazy loading <strong>reduces the initial bundle size</strong> and speeds up the initial load time of the application.</p>
</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { NgModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { RouterModule, Routes } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;
<span class="hljs-keyword">const</span> routes: Routes = [
  {
    path: <span class="hljs-string">'dashboard'</span>,
    loadChildren: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./dashboard/dashboard.module'</span>)
    .then(<span class="hljs-function"><span class="hljs-params">m</span> =&gt;</span> m.DashboardModule),
  },
];
<span class="hljs-meta">@NgModule</span>({
  imports: [RouterModule.forRoot(routes)],
  <span class="hljs-built_in">exports</span>: [RouterModule],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppRoutingModule {}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Here are some examples of how can you optimize and improve your Angular application, you can increase your <strong>Lighthouse</strong> stats by applying these examples.</p>
]]></content:encoded></item></channel></rss>