angular Archives - ProdSens.live https://prodsens.live/tag/angular/ News for Project Managers - PMI Wed, 03 Jul 2024 06:20:32 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.5 https://prodsens.live/wp-content/uploads/2022/09/prod.png angular Archives - ProdSens.live https://prodsens.live/tag/angular/ 32 32 Dynamically render columns in Angular material table https://prodsens.live/2024/07/03/dynamically-render-columns-in-angular-material-table/?utm_source=rss&utm_medium=rss&utm_campaign=dynamically-render-columns-in-angular-material-table https://prodsens.live/2024/07/03/dynamically-render-columns-in-angular-material-table/#respond Wed, 03 Jul 2024 06:20:32 +0000 https://prodsens.live/2024/07/03/dynamically-render-columns-in-angular-material-table/ dynamically-render-columns-in-angular-material-table

Did you know that you can dynamically render columns in #angular material table? No, I am not talking…

The post Dynamically render columns in Angular material table appeared first on ProdSens.live.

]]>
dynamically-render-columns-in-angular-material-table

Did you know that you can dynamically render columns in #angular material table?

No, I am not talking about simply adding/removing columns on click of button, but a more robust solution like shown in below.


   matColumnDef="boilingPoint">
     mat-header-cell *matHeaderCellDef mat-sort-header="boilingPoint">
      Boiling Point
    
     mat-cell *matCellDef="let element">{{ element.boilingPoint }}
  

As show in code above, it’s upto consumer component which column it needs to render This technique involves mainly 2 things

1st is hostDirectives – to attach MatSort with component.

It is needed so that consumer can use mat-sort-header if it wants

@Component({
  selector: 'table-dynamic-example',
  standalone: true,
  imports: [MatTableModule, MatSortModule],
  hostDirectives: [MatSort],
})

2nd is contentChildren – to get projected columns

Due to internal structure of MatTable, we can’t directly use content projection here using ng-content, hence contentChildren is needed

private customCols = contentChildren(MatColumnDef);

And finally render them in afterViewInit hook using MatTable.addColumnDef

Also make sure to attach host MatSort with dataSource‘s sort. Otherwise sorting will not work

ngAfterViewInit() {
    this.dataSource.sort = this.matSort;
    this.customCols().forEach((col) => {
      const columnName = col.name;
      this.matTable()?.addColumnDef(col);

      // need to wait until column is added
      this.ngZone.onStable.pipe(take(1)).subscribe(() => {
        this.columnsToDisplay.push(columnName);
      });
    });
  }
 mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  @for (column of displayedColumns; track column) {

   [matColumnDef]="column">
     mat-header-cell *matHeaderCellDef mat-sort-header>{{ column }}
     mat-cell *matCellDef="let element">{{ element[column] }}
  
  }

   mat-header-row *matHeaderRowDef="columnsToDisplay">
   mat-row *matRowDef="let row; columns: columnsToDisplay;">

That’s it! Full code is available on stackblitz

The post Dynamically render columns in Angular material table appeared first on ProdSens.live.

]]>
https://prodsens.live/2024/07/03/dynamically-render-columns-in-angular-material-table/feed/ 0
Angular CDK Tutorial: Automatically Resizing Textareas https://prodsens.live/2024/06/29/angular-cdk-tutorial-automatically-resizing-textareas/?utm_source=rss&utm_medium=rss&utm_campaign=angular-cdk-tutorial-automatically-resizing-textareas https://prodsens.live/2024/06/29/angular-cdk-tutorial-automatically-resizing-textareas/#respond Sat, 29 Jun 2024 00:20:48 +0000 https://prodsens.live/2024/06/29/angular-cdk-tutorial-automatically-resizing-textareas/ angular-cdk-tutorial:-automatically-resizing-textareas

By default, an HTML textarea control doesn’t expand or contract as content is added and removed. Sometimes this…

The post Angular CDK Tutorial: Automatically Resizing Textareas appeared first on ProdSens.live.

]]>
angular-cdk-tutorial:-automatically-resizing-textareas

By default, an HTML textarea control doesn’t expand or contract as content is added and removed. Sometimes this is ok, but often it would be better if we did have some control where we could allow the height to resize automatically, to better fit the content. Well, this is possible and, in fact, it’s really easy to do in Angular when using the CDK. In this example I’ll show you just how easy it is. Alright, let’s get to it!

The Demo Application

For the example in this post, we’ll be working with this demo application, Petpix. It’s an app where people can share cool images of their pets.

Under each image, there’s a description field where the user can add content to describe the image. We want this textarea to resize automatically as we add or remove text.

Example of a standard textarea not automatically resizing when adding and removing content

This is what we’re going to do in this example, and we’ll be using the Angular CDK TextFieldModule to do it quickly and easily.

Installing the Angular CDK

Ok, since we’re using the Angular CDK, you ‘ll need to make sure that, before you do anything else, you install it using the following command in your terminal within the root directory for your Angular application.

npm i @angular/cdk

Once we have it installed, we will be able to use the TextFieldModule to configure our description textarea to automatically size itself to the content within it.

Ok, let’s look at some code.

How to Auto-Resize textareas in Angular Using the cdkTextareaAutosize Directive

Within the slider component, at the bottom of the template, there’s a description form component. Let’s take a look at the template for this component to see what we’re working with.

Within the template, there’s a standard textarea element.

desription-form.component.html

 for="description">Image Description:
id="description" placeholder="Provide additional context about this image of your pet">

Now, this may vary some in different browsers, but here in Chrome, the default height for a textarea will show two rows of text. So, if we type in this textarea, then hit return to go to a new line, we can see that it fits two rows of text perfectly. Then if we hit return again and add another line, we get a scrollbar.

Example of a standard textarea not automatically resizing when adding and removing content

And this is what we want to change. To do this, we’ll add the cdkTextareaAutosize directive. But first, we need to import this module in our description form component.

desription-form.component.ts

...
import { TextFieldModule } from '@angular/cdk/text-field';

@Component({
    selector: 'app-description-form',
    ...
    imports: [ TextFieldModule ]
})
export class DescriptionFormComponent {
}

Ok, now we can switch back to the template and add the directive to the textarea.

desription-form.component.html

 ... cdkTextareaAutosize>

And that’s all we need, now let’s save and see how it works.

Now we can see that the textarea no longer defaults to a height of two rows, instead it accounts for only a single row. So the directive appears to be doing its job. But what’s a little odd is that there’s a scrollbar even when no text has been added. It does automatically resize as content is added, but when the content is cleared out, it doesn’t resize back down to the initial height.

Example of the cdkTextareaAutosize directive partially functioning but without the proper styles

So, it looks like it’s not working properly, but there’s a simple fix for these issues.

Including Angular CDK Auto-size Styles for Proper textarea Height Calculation

Now, I had to find this out the hard way, but in order for this directive to calculate the height properly, we need to include the text-field-autosize styles from the CDK. To include these, we can include them within our global stylesheet.

Now, I’m using SCSS so I’ll add a @use directive and then path to “@angular/cdk” to include these styles. Then I can use the @include directive to include the text-field-autosize mixin, which is the piece that contains the styles that we need.

global_styles.scss

@use '@angular/cdk';
@include cdk.text-field-autosize;

Now, it’s important to note that if you’re not using SCSS like me, you can instead import the text-field-prebuilt.css file, and that would include the styles needed for the proper height calculation.

@import '@angular/cdk/text-field-prebuilt.css';

But, I’m going to stick with SCSS for this example.

Alright, now that the styles have been imported, let’s save and see if it’s working correctly now.

Ok, this looks promising now right? There’s no more scrollbar. Now when we add and remove content, it should now resize properly too.

Example of the cdkTextareaAutosize directive functioning correctly with proper styles included

Nice, it all seems to be working correctly now.

So, if you use this directive, you’ll just need to be sure to add those styles or it’ll never work correctly.

Add Min and Max row Counts to Control Min and Max textarea Heights

Something else handy that we can do with the cdkTextareaAutosize directive is, we can control them minimum number of rows that we want it to be able to shrink to, as well as the maximum number of rows that we want it to be able to grow to.

There are two inputs that we can use for this, cdkAutosizeMinRows, and cdkAutoSizeMaxRows.

So, let’s add these to our textarea. Let’s go with a minimum of three rows, so it will never shrink below that, and let’s go with a max of six rows. So it will add a scrollbar when the content grows to seven or more rows.

desription-form.component.html


    ...
    cdkTextareaAutosize
    cdkAutosizeMinRows="3"
    cdkAutosizeMaxRows="6">

Ok, let’s save and see how it looks now.

Example of the cdkTextareaAutosize directive functioning with cdkAutosizeMinRows and cdkAutosizeMaxRows configured

Nice, now it’s taller. It fits three rows of text before it resizes. Then it grows as we add four, five, and six rows. And when we go to seven and beyond, now we get a scrollbar. Then, when we clear it all out, it goes back down to three rows.

Pretty nice right?

Conclusion

So there you go, now you have a quick and easy way to create a textarea that automatically resizes in Angular. And it doesn’t take much effort at all thanks to the Angular CDK.

I hope you found this tutorial helpful, and if you did, check out my YouTube channel for more tutorials on the Angular CDK and Angular in general.

Want to See It in Action?

Check out the demo code and examples of these techniques in the in the Stackblitz example below. If you have any questions or thoughts, don’t hesitate to leave a comment.

Found This Helpful?

If you found this article helpful and want to show some love, you can always buy me a coffee!

The post Angular CDK Tutorial: Automatically Resizing Textareas appeared first on ProdSens.live.

]]>
https://prodsens.live/2024/06/29/angular-cdk-tutorial-automatically-resizing-textareas/feed/ 0
Building PDF Open Source Services with Angular & GCP — Deploy services to Cloud Run https://prodsens.live/2024/06/08/building-pdf-open-source-services-with-angular-gcp-deploy-services-to-cloud-run/?utm_source=rss&utm_medium=rss&utm_campaign=building-pdf-open-source-services-with-angular-gcp-deploy-services-to-cloud-run https://prodsens.live/2024/06/08/building-pdf-open-source-services-with-angular-gcp-deploy-services-to-cloud-run/#respond Sat, 08 Jun 2024 20:20:25 +0000 https://prodsens.live/2024/06/08/building-pdf-open-source-services-with-angular-gcp-deploy-services-to-cloud-run/ building-pdf-open-source-services-with-angular-&-gcp-—-deploy-services-to-cloud-run

Welcome to the journey of building open source PDF service using Angular (Analogjs), Firestore, Cloud Storage, and CloudRun.…

The post Building PDF Open Source Services with Angular & GCP — Deploy services to Cloud Run appeared first on ProdSens.live.

]]>
building-pdf-open-source-services-with-angular-&-gcp-—-deploy-services-to-cloud-run

Welcome to the journey of building open source PDF service using Angular (Analogjs), Firestore, Cloud Storage, and CloudRun. This project serves as a platform for sharing my knowledge, continually learning best practices, and simultaneously contributing to the community.

Part 1: Architecture Overview
Part 2: Deploy services to Cloud Run

Demo: https://pdfun.xyz
GitHub: https://github.com/dalenguyen/pdfun

The solution is built around GCP ecosystem, it’s better to deploy the project on GCP, so it can access their services. There are two parts of the solution:

  • Web UI (Analogjs — Angular): handle user interaction
  • Backend (Node — Express): process PDF files

Why Deploy to Cloud Run?

Cloud Run is a fully managed compute platform by Google Cloud Platform (GCP) that automatically scales your stateless containers. But why should we choose Cloud Run for deploying our services? Here are some reasons:

  • Cloud Run is an excellent choice for deploying services due to its support for long-running tasks. Services can run for up to 60 minutes, accommodating tasks that require significant computation time.
  • In addition to this, Cloud Run offers benefits such as automatic scaling, a developer-friendly environment, integrated logging and monitoring, a pay-per-use pricing model, and portability across different platforms. This makes it a versatile and cost-effective solution for deploying our PDF service.

Deploying to Google Cloud Run using Docker

Cloud Run using a docker image to deploy its service, so what we need to do is to wrap our applications into a image.

Prerequisites

Before we begin, make sure you have the following:

  • A Google Cloud project with billing enabled.
  • Docker installed on your local machine.
  • The Google Cloud SDK installed and initialized.

Please follow the Deploying to Cloud Run documentation for further instruction.

Build Your Docker Image

Next, you will need to build your project and the Docker image. This can be done using the docker build command. Make sure to tag your image with the registry name. For example:

// build-new-image.sh

imageTag=${REGION}-docker.pkg.dev/$GCLOUD_PROJECT/$REPO/$image

docker build -t $imageTag -f Dockerfile --platform linux/x86_64 .

Replace REGIONS, GCLOUD_PROJECT, REPO and image with your Google Cloud project ID, your image name, and your image tag, respectively.

Push Your Image to the Artifact Registry

Once your image is built, you can push it to the Artifact Registry using the docker push command:

docker push $imageTag

Create a New Service in Cloud Run

With your image now in the Artifact Registry, you can create a new service in Cloud Run. You can run the following command to deploy the PDF service:

gcloud run deploy pdfun 
  --image=us-central1-docker.pkg.dev/pdfun-prod/pdf/pdfun 
  --platform=managed --project=pdfun-prod --region=us-central1 
  --allow-unauthenticated

This command will deploy the Web UI with service name pdfun to Cloud Run and allows every one to access the website (--allow-unauthenticated).

Bonus: Utilizing Nx to deploy services

Nx is a development framework designed for building applications inside monorepos. Monorepos contain multiple apps inside a single Git repository, allowing organizations to share code, such as components and utility libraries, across apps and teams. Nx handles many monorepo use cases like build systems, inbuilt tools, and smart caching.

When it comes to deploying services, Nx offers a streamlined process. After configuration, all I need to do is to run yarn deploy in order deploy only affected apps. For example, if I only update the frontend, then the frontend is the only app that will be built and deployed.

Here is what happens under the hood after I run the deploying command:

npx nx affected -t deploy --base=main~1 --head=main

This command will run the deploy target under project.json for affected projects by comparing the commit and the latest commit on main branch.

Let’s have a look at the project.json for the pdfun application:

// project.json

...

"deploy": {
  "executor": "nx:run-commands",
  "options": {
    "commands": ["nx deploy-docker pdf", "nx deploy-cloudrun pdf"],
    "color": true,
    "parallel": false
  },
  "dependsOn": [
    {
      "target": "build"
    }
  ]
},
"deploy-cloudrun": {
  "command": "gcloud run deploy pdfun --image=us-central1-docker.pkg.dev/pdfun-prod/pdf/pdfun --platform=managed --project=pdfun-prod --region=us-central1 --allow-unauthenticated"
},
"deploy-docker": {
  "command": "./build-new-image.sh --dir dist/pdf/analog --image pdfun",
  "parallel": false,
  "dependsOn": [
    {
      "target": "copy"
    }
  ]
},

So, when the deploy target runs, it will trigger two other commands:

npx nx deploy-docker pdf
npx nx deploy-cloudrun pdf

These commands in turn will build the docker image, push the image and deploy the Cloud Run service based on the uploaded image on Artifact Registry.

Here is the result:

dalenguyen$ yarn deploy

yarn run v1.22.19
$ npx nx affected -t deploy --base=main~1 --head=main

 NX   Running target deploy for 2 projects and 3
 NX   Running target deploy for 2 projects and 3 tasks they depend on

   ✔  nx run domain:build (6s)
———————————————————————————————————————————————
   ✔  nx run pdf:build:production (17s)
———————————————————————————————————————————————
   ✔  nx run pdf:deploy (17s)
   ✔  nx run pdf-on-create:deploy (29s)
———————————————————————————————————————————————

 NX   Successfully ran target deploy for 2 projects and 3 tasks they depend on (37s)

You can see that the by utilizing the build cache, two services were build and deploy in about 1 minute locally!

Questions?

If you have any questions or run into any issues, please don’t hesitate to create an issue on our GitHub repository. Alternatively, you can chat with me. I’m here to help and would love to hear your feedback.

Stay tuned for the next part. Until then, happy coding!

The post Building PDF Open Source Services with Angular & GCP — Deploy services to Cloud Run appeared first on ProdSens.live.

]]>
https://prodsens.live/2024/06/08/building-pdf-open-source-services-with-angular-gcp-deploy-services-to-cloud-run/feed/ 0
Guía Completa sobre Pruebas Unitarias en Angular 16 https://prodsens.live/2024/05/28/guia-completa-sobre-pruebas-unitarias-en-angular-16/?utm_source=rss&utm_medium=rss&utm_campaign=guia-completa-sobre-pruebas-unitarias-en-angular-16 https://prodsens.live/2024/05/28/guia-completa-sobre-pruebas-unitarias-en-angular-16/#respond Tue, 28 May 2024 04:20:54 +0000 https://prodsens.live/2024/05/28/guia-completa-sobre-pruebas-unitarias-en-angular-16/ guia-completa-sobre-pruebas-unitarias-en-angular-16

Las pruebas unitarias son una parte esencial del desarrollo de software, ya que garantizan que cada componente de…

The post Guía Completa sobre Pruebas Unitarias en Angular 16 appeared first on ProdSens.live.

]]>
guia-completa-sobre-pruebas-unitarias-en-angular-16

Las pruebas unitarias son una parte esencial del desarrollo de software, ya que garantizan que cada componente de nuestra aplicación funcione correctamente. En este artículo, veremos cómo realizar pruebas unitarias en Angular 16, una de las versiones no tan recientes pero potentes de este popular framework.

¿Qué son las Pruebas Unitarias?

Son pruebas automáticas que validan el comportamiento de una unidad de código, como una función o un componente. Estas pruebas son fundamentales para asegurar que el código funcione según lo esperado y para facilitar el mantenimiento y la evolución de la aplicación.

Beneficios de las Pruebas Unitarias en Angular

  1. Detección Temprana de Errores: Permiten identificar y corregir errores en etapas tempranas del desarrollo.
  2. Facilitan el Refactorizado: Al tener una suite de pruebas, podemos refactorizar el código con confianza, sabiendo que cualquier cambio que rompa la funcionalidad será detectado.
  3. Mejoran la Documentación: Las pruebas actúan como una documentación viva del comportamiento esperado de la aplicación.
  4. Aumentan la Confianza en el Código: Desarrolladores y stakeholders pueden tener mayor confianza en la estabilidad y la calidad del código.

Configuración Inicial

Para empezar a trabajar con pruebas unitarias en Angular 16, necesitamos tener configurado nuestro entorno de desarrollo. Asumiremos que ya tienes Node.js y Angular CLI instalados.

1.- Crear un Nuevo Proyecto Angular:

ng new angular-testing
cd angular-testing

2.- Instalar Dependencias Necesarias:
Angular ya viene con Jasmine y Karma configurados para pruebas unitarias. Jasmine es el framework de pruebas y Karma es el ejecutor de pruebas.

Estructura de una Prueba Unitaria en Angular

Supongamos que tenemos un servicio simple llamado DataService:

// src/app/data.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  getData(): string {
    return 'Hello, Angular 16!';
  }
}

Crear la Prueba Unitaria

Vamos a crear una prueba unitaria para este servicio.

// src/app/data.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { DataService } from './data.service';

describe('DataService', () => {
  let service: DataService;

  beforeEach(() => {
    TestBed.configureTestingModule({});
    service = TestBed.inject(DataService);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  it('should return "Hello, Angular 16!"', () => {
    const data = service.getData();
    expect(data).toBe('Hello, Angular 16!');
  });
});

Desglose de la Prueba

  1. Configuración del Módulo de Pruebas: TestBed.configureTestingModule se usa para configurar y compilar el entorno de pruebas para el servicio.
  2. Inyección del Servicio: TestBed.inject(DataService) se usa para obtener una instancia del servicio que queremos probar.
  3. Expectativas: Utilizamos expect para verificar que el servicio se crea correctamente y que el método getData devuelve el valor esperado.

Pruebas Unitarias de Componentes

Vamos a crear un componente simple y escribir pruebas unitarias para él.

// src/app/hello.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello',
  template: '

{{ title }}

' }) export class HelloComponent { title = 'Hello, Angular 16!'; }

Crear la Prueba Unitaria para el Componente

// src/app/hello.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HelloComponent } from './hello.component';

describe('HelloComponent', () => {
  let component: HelloComponent;
  let fixture: ComponentFixture;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [HelloComponent]
    }).compileComponents();

    fixture = TestBed.createComponent(HelloComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should have title "Hello, Angular 16!"', () => {
    const compiled = fixture.nativeElement as HTMLElement;
    expect(compiled.querySelector('h1')?.textContent).toBe('Hello, Angular 16!');
  });
});

Desglose de la Prueba de Componente

  1. Configuración del Módulo de Pruebas: Se declara el componente HelloComponent en el módulo de pruebas.
  2. Creación del Componente: TestBed.createComponent se usa para crear una instancia del componente.
  3. Detección de Cambios: fixture.detectChanges se llama para actualizar el DOM con los cambios del componente.
  4. Expectativas: Verificamos que el componente se crea correctamente y que el título se renderiza como se espera.

Ejecutar las Pruebas

Para ejecutar las pruebas, simplemente corre el siguiente comando:

ng test

Este comando ejecutará Karma, que abrirá un navegador y ejecutará todas las pruebas unitarias, mostrando los resultados en tiempo real.

Conclusión

Las pruebas unitarias son una herramienta poderosa para mantener la calidad del código en proyectos Angular. Angular 16 proporciona un entorno robusto y fácil de usar para escribir y ejecutar estas pruebas. Al seguir buenas prácticas y realizar pruebas constantes, puedes asegurarte de que tu aplicación sea confiable y fácil de mantener.

Espero que esta guía te haya proporcionado una comprensión clara y útil sobre cómo implementar pruebas unitarias en Angular 16.

The post Guía Completa sobre Pruebas Unitarias en Angular 16 appeared first on ProdSens.live.

]]>
https://prodsens.live/2024/05/28/guia-completa-sobre-pruebas-unitarias-en-angular-16/feed/ 0
I give up on AngularFire https://prodsens.live/2024/05/25/i-give-up-on-angularfire/?utm_source=rss&utm_medium=rss&utm_campaign=i-give-up-on-angularfire https://prodsens.live/2024/05/25/i-give-up-on-angularfire/#respond Sat, 25 May 2024 22:20:45 +0000 https://prodsens.live/2024/05/25/i-give-up-on-angularfire/ i-give-up-on-angularfire

I just worked really hard to rip AngularFire (@angular/fire) out of my codebase. If you don’t know, AngularFire…

The post I give up on AngularFire appeared first on ProdSens.live.

]]>
i-give-up-on-angularfire

I just worked really hard to rip AngularFire (@angular/fire) out of my codebase.

If you don’t know, AngularFire used to be awesome. This was best around 2019-2020, but after being under-served and failing to fully finish several migrations (the Firebase SDK now uses a modular approach), it’s kind of a mess.

I tried and failed to update from v6 up to v16, v17, and beyond, because I wanted to use Angular 18. This didn’t work (ng update would refuse to update to v16 because it forces only updating one major at a time, which is a bit silly), so I ended up deciding to rip it out.

Steps to remove

  • Remove @angular/fire from your package.json
  • Swap out the AngularFireModulesfor your own keys
providers: [
  { provide: BUCKET, useValue: '...'},
  { provide: FIREBASE_APP, useFactory: () => initializeApp({...})}
  • Create a service that calls initializeApp from firebase/app and save yourFirebaseApp.

    constructor(@Inject(FIREBASE_APP) private fbApp: FirebaseApp) {
    `
  • Create (or use the same) a service for each of the Firebase modules you want to use, and then get a persistent handle on the service you want.
    typescript
    db = getDatabase(this.fbApp);
    storage = getStorage(this.fbApp);
    auth = getAuth(this.fbApp);

Here’s the commit on the fluin.io repo.

The post I give up on AngularFire appeared first on ProdSens.live.

]]>
https://prodsens.live/2024/05/25/i-give-up-on-angularfire/feed/ 0
Demystifying Angular 17 SSR: A Simple Guide to Understanding the Rendering Process https://prodsens.live/2024/05/22/demystifying-angular-17-ssr-a-simple-guide-to-understanding-the-rendering-process/?utm_source=rss&utm_medium=rss&utm_campaign=demystifying-angular-17-ssr-a-simple-guide-to-understanding-the-rendering-process https://prodsens.live/2024/05/22/demystifying-angular-17-ssr-a-simple-guide-to-understanding-the-rendering-process/#respond Wed, 22 May 2024 22:20:48 +0000 https://prodsens.live/2024/05/22/demystifying-angular-17-ssr-a-simple-guide-to-understanding-the-rendering-process/ demystifying-angular-17-ssr:-a-simple-guide-to-understanding-the-rendering-process

A 2018 PacketZoom study found that 63% of users abandon an app that takes more than 5 seconds…

The post Demystifying Angular 17 SSR: A Simple Guide to Understanding the Rendering Process appeared first on ProdSens.live.

]]>
demystifying-angular-17-ssr:-a-simple-guide-to-understanding-the-rendering-process

A 2018 PacketZoom study found that 63% of users abandon an app that takes more than 5 seconds to load, and 71% of users expect apps to load within 3 seconds. Server-side rendering (SSR) addresses these expectations by generating the initial HTML content on the server, leading to faster initial page loads and potentially reducing user abandonment rates. This means that when a user request a page, the server generates the HTML content for that page dynamically and sends it to the browser as a complete HTML document.

How SSR Works

When a user requests a page, the server dynamically generates the HTML content for that page and dispatches it to the browser as a complete HTML document. This allows the browser to commence parsing and displaying the content even before fetching the requisite JavaScript for the application

Implementing SSR enhances performance, user experience, and search engine visibility, making it a valuable technique for web development.

Why use SSR?

Improved Performance:

SSR can enhance the performance of web applications by delivering fully rendered HTML to the client. This means that the browser can start parsing and displaying the content even before it downloads the JavaScript required for the application. This is particularly beneficial for users on low-bandwidth connections or mobile devices.

Improved Core Web Vitals:

SSR often results in performance improvements that can be measured using Core Web Vitals metrics, such as reduced First Contentful Paint (FCP) and Largest Contentful Paint (LCP), as well as Cumulative Layout Shift (CLS).

Better SEO:

SSR can improve the search engine optimization (SEO) of web applications by making it easier for search engines to crawl and index the content of the application.

Better User Experience:

Users experience faster load times, resulting in a smoother and more engaging experience.

Instances SSR might be beneficial:

1. Content-heavy websites:
Example: A news website that publishes numerous articles daily. Implementing SSR ensures that users can access content quickly, even on slower connections or devices.

2. SEO optimization:
Example: An e-commerce platform that wants its product pages to rank higher in search engine results. By using SSR, the platform ensures that search engines can crawl and index product information effectively.

3. Social sharing:
Example: A blog platform where users frequently share articles on social media platforms like Facebook and Twitter. SSR ensures that when articles are shared, the correct title, description, and image are displayed, improving click-through rates.

4. First-time user experience:
Example: A travel website where users often land on specific destination pages through search results, their initial experience is crucial. SSR enables the website to load relevant content quickly, providing users with a positive first impression and encouraging further exploration.

However, using SSR bears certain drawbacks:

1. Complexity and Overhead: Implementing SSR adds complexity to development workflows and may require additional server resources, leading to increased maintenance overhead.

2. Increased Initial Server Load: Handling server-side rendering requests may strain server resources, particularly during periods of high traffic, leading to slower response times or server downtime.

3. Limited Compatibility with Third-Party Libraries: SSR may introduce compatibility challenges with certain third-party libraries or components that rely heavily on client-side rendering, requiring additional effort to ensure seamless integration.

Instances SSR might not be beneficial:

1. Highly Interactive Applications:

SSR is less suitable for highly interactive applications with complex client-side logic, such as real-time gaming platforms or sophisticated web-based tools.

2. Dynamic Content:

Applications that heavily rely on dynamic content generation based on user interactions or data input may not benefit significantly from SSR. Since SSR generates HTML on the server before sending it to the client, it may not capture dynamic changes that occur after the initial render without additional client-side updates.

Example: A social media feed where content frequently updates based on user interactions (likes, comments, etc.)

3. Resource-Intensive Applications:

SSR can introduce performance overhead, especially for resource-intensive applications that require heavy server-side processing or complex data computations. In such cases, SSR may strain server resources and slow down the rendering process, negatively impacting user experience.

Example: A data visualization tool that processes large datasets and generates complex interactive charts or graphs. SSR might not be suitable because of the computational overhead involved in rendering these visualizations on the server.

Enabling Server-side Rendering

1. Creating a New Application with SSR: To create a new Angular application with SSR, run the following command:

ng new app-name --ssr

2. Adding SSR to an Existing Project: If you already have an Angular project and want to add SSR to it, run:

ng add @angular/ssr 

After running either of the above commands, your project structure will be updated.

You’ll have a new file named server.ts at the root of your project. This file is for the application server.

Inside the src folder, there will be additional files:

– app.config.server.ts: This file is for server application
configuration.
– main.server.ts: This file handles the main server
application bootstrapping.

To verify it worked run the application and view the Page Source, you should now see that the typical empty will now have content inside it that is accessible to search crawlers.

Hydration

Angular hydration refers to the process of converting static HTML content generated by the server into dynamic Angular components on the client-side.

Hydration involves reusing the pre-rendered HTML from the server to reconstruct the DOM (Document Object Model) on the client-side.

Without hydration enabled, server side rendered Angular applications will destroy and re-render the application’s DOM, which may result in a visible UI flicker.

Hydration ensures that users experience a smooth transition from static server-rendered content to an interactive client-side application without any noticeable delays or inconsistencies.

Hydration process expects the same DOM tree structure in both the server and the client, a mismatch will cause problems in the hydration process

To make sure the hydration process is quick and efficient, aim to keep the initial server-rendered version as light as possible.

Enabling Hydration

Hydration is enabled by default when you use SSR.

You can enable hydration by following the below steps:

1. Import provideClientHydration:

In your app.config.ts import provideClientHydration from @angular/platform-browser

import { provideClientHydration } from '@angular/platform-browser';
  1. Add provideClientHydration to Providers:
export const appConfig: ApplicationConfig = {
  providers: [provideClientHydration()]
};

Code which utilizes browser-specific symbols such as window, document, navigator, or location should only be executed in the browser, not on the server. This can be enforced through the afterRender (triggers after every change detection cycle) and afterNextRender (runs once and also after the change detection) lifecycle hooks which are only executed on the browser. These hooks can be called in any injection context, such as the constructor of a component or a service, as demonstrated in the example below:

import { Component, ElementRef, Input, ViewChild, afterNextRender, afterRender } from '@angular/core';
import { ProductService } from '../product.service';
import { Product } from '../product';
import { CommonModule } from '@angular/common';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-product-detail',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './product-detail.component.html',
  styleUrl: './product-detail.component.css'
})
export class ProductDetailComponent{
  @ViewChild('productDetail') productDetailRef!: ElementRef;

  @Input() set id(id: number) {
    this.product$ = this.productService.getProductById(id);    
  }

  product$!: Observable;

  constructor(private productService: ProductService) {
    afterRender(() => {
      const height = this.measureHeight();
      console.log('After Render height: ' + height + 'px');
    });

    afterNextRender(() => {
      const height = this.measureHeight();
      console.log('After Next Render height: ' + height + 'px');
    });
  }

  measureHeight() {
    const height = this.productDetailRef.nativeElement.offsetHeight;
    return height;
  }

}

Skipping Hydration

Some components may not work properly with hydration enabled due to some of the following reasons:

1. Direct DOM Manipulation:

Components manipulating the DOM directly using native DOM APIs or methods like innerHTML, outerHTML, appendChild, etc., can cause a mismatch between expected and actual DOM structures during hydration.

2. Invalid HTML Structure:

Component templates with invalid HTML structure, such as

without a

, or nested tags, may lead to hydration errors.

3. Preserve Whitespaces Configuration:

Inconsistent configuration or enabling preserveWhitespaces in tsconfig.json can cause issues during hydration. It’s recommended to keep this setting false for hydration to function properly. If this setting is not in your tsconfig.json, the value will be false and no changes are required.

4. CDN Optimizations:

CDN optimization features that strip out nodes considered unnecessary, including comment nodes, can disrupt hydration. Disabling such optimizations is necessary to ensure proper hydration.

5. Custom or Noop Zone.js:

Using custom or “noop” Zone.js implementations may lead to timing issues with Zone.js signals, affecting hydration timing events like onStable. Adjustments may be needed to ensure proper synchronization.

As a workaround you can skip hydration for particular components encountering issues. The following are the ways in which you can do that:

  1. Add the ngSkipHydration attribute directly to the component’s tag:

  1. Alternatively, you can set ngSkipHydration as a host binding in the component decorator. The host property allows you to define how your component interacts with its host element in the DOM
@Component({
  ...
  host: { ngSkipHydration: 'true' },
})
class ExampleCmp {}

The ngSkipHydration attribute can only be used on component host nodes.

Both of the approach will skip hydrating the entire component and its children.

However, keep in mind that by skipping hydration, the component will behave as if hydration is not enabled, resulting in the component being destroyed and re-rendered. Additionally, applying ngSkipHydration to the root application component would effectively disable hydration for the entire application

Remember, using ngSkipHydration should be a last resort. Components that break hydration should ideally be fixed rather than worked around.

Optimization Techniques

1. Caching for Efficiency
When SSR is enabled, HttpClient responses are cached while running on the server.

HttpClient caches all HEAD and GET requests which don’t contain Authorization or Proxy-Authorization headers by default.

HttpClient checks whether it has data in the cache and if so, reuses it instead of making a new HTTP request during initial application rendering. HttpClient stops using the cache once an application becomes stable (meaning that the initial loading and rendering processes have completed) while running in a browser.

POST requests are not typically cached by default due to their dynamic nature, you have the option to include them in the caching mechanism using configuration options like includePostRequests when configuring HttpClient for SSR in your app.config.ts file.

providers: [
    provideClientHydration(
      withHttpTransferCacheOptions({
        includePostRequests: true,
      }),
    ),
  ]

2. Lazy Loading
Lazy load modules through implementation of deferrable views to reduce initial bundle size.

Conclusion

Server-Side Rendering offers numerous benefits for web developers seeking to optimize performance, improve SEO, and enhance user experience. However, it’s essential to weigh these benefits against the potential challenges and complexities involved in implementing and maintaining SSR in a web application.

CTA

Many developers and learners encounter tutorials that are either too complex or lacking in detail, making it challenging to absorb new information effectively.

Subscribe to our newsletter today, to access our comprehensive guides and tutorials designed to simplify complex topics and guide you through practical applications.

The post Demystifying Angular 17 SSR: A Simple Guide to Understanding the Rendering Process appeared first on ProdSens.live.

]]>https://prodsens.live/2024/05/22/demystifying-angular-17-ssr-a-simple-guide-to-understanding-the-rendering-process/feed/0 Episode 24/20: Angular Talks at Google I/O, JSWorld, TiL https://prodsens.live/2024/05/20/episode-24-20-angular-talks-at-google-i-o-jsworld-til/?utm_source=rss&utm_medium=rss&utm_campaign=episode-24-20-angular-talks-at-google-i-o-jsworld-til https://prodsens.live/2024/05/20/episode-24-20-angular-talks-at-google-i-o-jsworld-til/#respond Mon, 20 May 2024 19:20:38 +0000 https://prodsens.live/2024/05/20/episode-24-20-angular-talks-at-google-i-o-jsworld-til/ episode-24/20:-angular-talks-at-google-i/o,-jsworld,-til

Last week, we had the Google I/O and the release of the JSWorld conference recordings. Both conferences features…

The post Episode 24/20: Angular Talks at Google I/O, JSWorld, TiL appeared first on ProdSens.live.

]]>
episode-24/20:-angular-talks-at-google-i/o,-jsworld,-til

Last week, we had the Google I/O and the release of the JSWorld conference recordings. Both conferences features talks of the Angular team.

Release Date Angular 18

Angular 18 will be released this week. There are some upcoming release parties scheduled for Thursday, the 23rd of May. For the official one, head to Angular’s official YouTube channel at


Angular an application development platform that lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop.

For more info, visit http://angular.io

favicon
youtube.com

Google I/O

Google’s tech conference, Google I/O happened last week. The videos are available on YouTube


Join us as we reimagine how AI can make your life better and help you explore your creativity, connect with the world, and discover new possibilities. Subscribe for the latest product updates, innovations, and a peek inside the magic of Google.

favicon
youtube.com

The Angular talk at I/O provided an overview of the latest features and what to expect in the upcoming versions. The Angular team’s representatives were Jessica Janiuk, Jeremy Elbourn, and Minko Gechev. They focused on improvements in hydration and zonelessness.

Jeremy also mentioned the authoring format and selector components. “Selectorless” means a component’s selector and the required import in a parent component disappear. This will be another upcoming feature that will reduce boilerplate.

Interestingly, though, Jeremy mentioned the Analog format, which has caused quite some heavy debates in the past


Analog SFCs | Analog

Note:

favicon
analogjs.org

Jeremy said that they have similar views in terms of identifying the problems and solutions when it comes to the authoring format.


What’s new in Angular – YouTube

Find out about the latest from Angular, including updates on server-side rendering and reactivity. Discover everything from community updates and the request…

favicon
youtube.com

JSWorld

JSWorld, another conference, published their recordings as well. The top talk was “Web Development at Google”. Those were three sub-talks from Aurora, a team that collaborates with different tools to improve the web. The other two talks were about Angular and Wiz, which recently announced that they are joining forces.

Jatin Ramanathan from Wiz explained the behavior of JSAction, which will be a cornerstone for the upcoming partial hydration in Angular.


JSWorld Conference Replay 2024 – YouTube

Watch the JSworld Conference 2024 Replay and you will learn about.. 👉 Discover why building a modular and performant Composable Data Platform with Vue and V…

favicon
youtube.com

There was also a panel discussion between different framework/tooling authors on a wide range of topics, such as Signals, PWA, and AI.

TiL Conference

The “This is Learning” conference with different topics also took place. The recordings of the live stream are available on YouTube:

The post Episode 24/20: Angular Talks at Google I/O, JSWorld, TiL appeared first on ProdSens.live.

]]>
https://prodsens.live/2024/05/20/episode-24-20-angular-talks-at-google-i-o-jsworld-til/feed/ 0
Angular HostAttributeToken: the new way to inject attributes https://prodsens.live/2024/04/21/angular-hostattributetoken-the-new-way-to-inject-attributes/?utm_source=rss&utm_medium=rss&utm_campaign=angular-hostattributetoken-the-new-way-to-inject-attributes https://prodsens.live/2024/04/21/angular-hostattributetoken-the-new-way-to-inject-attributes/#respond Sun, 21 Apr 2024 22:20:23 +0000 https://prodsens.live/2024/04/21/angular-hostattributetoken-the-new-way-to-inject-attributes/ angular-hostattributetoken:-the-new-way-to-inject-attributes

Over the latest months Angular has been evolving rapidly, introducing new features and a ton of improvements, many…

The post Angular HostAttributeToken: the new way to inject attributes appeared first on ProdSens.live.

]]>
angular-hostattributetoken:-the-new-way-to-inject-attributes

Over the latest months Angular has been evolving rapidly, introducing new features and a ton of improvements, many of these with the aim of improving maintainability and performance.

In this article I want to introduce you to the latest addition brought by Angular v17.3.0: the new HostAttributeToken class.

This new API allows you to inject host attributes using the inject() function, similar to the functionality of the @Attribute decorator.

The @Attribute decorator is perhaps the lesser-known Angular decorators.
Therefore, before delving into how the HostAttributeToken class works, let’s take a moment to review the fundamentals.

@Attribute: do you really need an input?

Let’s start from a simple scenario in which you want to develop a component requiring a configurable property.

Specifically, you want to provide this property as a constant string literal, because it will not change throughout runtime:

 size="small" />

What you would normally do is to create an input for that property:

import { Component, Input } from '@angular/core';

export type DividerSize = 'small' | 'big';

@Component({
  selector: 'my-divider',
  template: '
', standalone: true, }) export class MyDivider { @Input() size: DividerSize; }

Which is fine and works quite well. Perhaps too much…

Meme - Well done. BUT...

By creating an input, you are instructing Angular to create a binding to that property and check it during each change detection cycle.

That is really excessive, you only need that property to be checked once during component initialization. 🤯

To make this more performant you can instead inject the host-element attribute in the constructor thanks to the @Attribute decorator:

import { Attribute, Component } from '@angular/core';

export type DividerSize = 'small' | 'big';

@Component({
  selector: 'my-divider',
  template: '
', standalone: true, }) export class MyDivider { constructor(@Attribute('size') size: string) {} }

Using @Attribute, Angular will read the value only once and never again.

Note: This approach works as well with Directives, feel free to give it a shot!!!

Now that we have covered the basics, let me introduce you to the main topic of this article: new HostAttributeToken class.

Meme - Finally, let's talk about new stuff!

Inject an Attribute using HostAttributeToken class

Since the release of Angular 14 there is now a cleaner approach to inject providers without using the constructor class: the inject() function.

Up until now, this inject() function allowed to inject easily components, directives and pipes, but it was missing a method to inject host attributes.

And that’s precisely why the HostAttributeToken class was introduced:

import { Component, HostAttributeToken, inject } from '@angular/core';

export type DividerSize = 'small' | 'big';

@Component({
  selector: 'my-divider',
  template: '
', standalone: true, }) export class MyDivider { size: string = inject( new HostAttributeToken('size') ); }

By injecting an HostAttributeToken class within the inject function, you get the corresponding host-element attribute value.

This new API works similarly to @Attribute, with a notable difference: instead of returning null when the attribute is missing, it throws an error.

🔥 Error: NG0201: No provider for HostAttributeToken size found. 🔥

This change was made to align the behavior with other injection tokens.

Thanks for reading so far 🙏

I’d like to have your feedback so please leave a comment, like or follow. 👏

Then, if you really liked it, share it among your community, tech bros and whoever you want. And don’t forget to follow me on LinkedIn. 👋😁

The post Angular HostAttributeToken: the new way to inject attributes appeared first on ProdSens.live.

]]>
https://prodsens.live/2024/04/21/angular-hostattributetoken-the-new-way-to-inject-attributes/feed/ 0
How to Serve an Angular App with Nginx https://prodsens.live/2024/04/15/how-to-serve-an-angular-app-with-nginx/?utm_source=rss&utm_medium=rss&utm_campaign=how-to-serve-an-angular-app-with-nginx https://prodsens.live/2024/04/15/how-to-serve-an-angular-app-with-nginx/#respond Mon, 15 Apr 2024 17:20:46 +0000 https://prodsens.live/2024/04/15/how-to-serve-an-angular-app-with-nginx/ how-to-serve-an-angular-app-with-nginx

Installing Nginx on Windows 1… – Download the latest version of Nginx for Windows from the official Nginx…

The post How to Serve an Angular App with Nginx appeared first on ProdSens.live.

]]>
how-to-serve-an-angular-app-with-nginx

Installing Nginx on Windows

1… – Download the latest version of Nginx for Windows from the official Nginx website.

2… – Extract the downloaded archive to a directory of your choice, such as C:nginx.

nginx.conf Configuration

  • Next, let’s configure Nginx to serve our Angular application. Below is a basic configuration file (nginx.conf) for serving an Angular app:
http {
    include mime.types;
    server {
        listen 2292;
        root /Users/vivek/Desktop/SAAS/saas_client/dist/sfms/browser;
    }
}
events{}

Explanation of Configuration

The provided Nginx configuration file consists of the following directives:

  • http This directive marks the beginning of the HTTP block, which defines global settings for Nginx.

  • include mime.types; This directive includes the mime.types file, which maps file extensions to their corresponding MIME types.

  • server This directive defines a server block within the HTTP block. A server block defines how Nginx handles requests for a specific domain name or port.

  • listen 2292; This directive specifies the port (2292) on which Nginx should listen for incoming connections.

  • root /Users/vivek/Desktop/SAAS/saas_client/dist/sfms/browser; This directive sets the root directory from which Nginx should serve static files. [above location is location of build artifacts]

  • In this case, the Angular application’s built output is located in the specified directory.

Replacing Default nginx.conf

  • To use the above configuration, follow these steps:

3… Locate the default nginx.conf file in the Nginx installation directory (typically C:nginxconf on Windows).

4… Replace the contents of the default nginx.conf file with the configuration provided above.

5… Save the changes to the nginx.conf file.

Basic Nginx Commands

  • To start Nginx: Open Command Prompt and navigate to the Nginx directory (cd C:nginx) and then run nginx.exe.

  • To stop Nginx: Use the command nginx.exe -s stop.

  • To reload Nginx configuration: Use the command nginx.exe -s reload.

6… go to browser and hit localhost:2209

7… its done!!!😀

The post How to Serve an Angular App with Nginx appeared first on ProdSens.live.

]]>
https://prodsens.live/2024/04/15/how-to-serve-an-angular-app-with-nginx/feed/ 0
Angular Material Update Guide https://prodsens.live/2024/03/30/angular-material-update-guide/?utm_source=rss&utm_medium=rss&utm_campaign=angular-material-update-guide https://prodsens.live/2024/03/30/angular-material-update-guide/#respond Sat, 30 Mar 2024 11:20:48 +0000 https://prodsens.live/2024/03/30/angular-material-update-guide/ angular-material-update-guide

🚀New Chapter Added! A complete update guide for Angular Material from v10 to v17 Are you struggling with…

The post Angular Material Update Guide appeared first on ProdSens.live.

]]>
angular-material-update-guide

🚀New Chapter Added!

A complete update guide for Angular Material from v10 to v17

Are you struggling with updating Angular Material to latest version?

Then this chapter is just for you.

If your current project uses Angular Material version older than 17 and wants to update to version 17, then follow this chapter.

In this chapter, I will provide step-by-step guide to update Angular Material library to latest version.

Not just the CLI commands, but also fixes to some issues which you would face when making the upgrade.

Read it at https://angular-material.dev/courses/m2-ng-components/m2-ng-components/update-guide

Image description

The post Angular Material Update Guide appeared first on ProdSens.live.

]]>
https://prodsens.live/2024/03/30/angular-material-update-guide/feed/ 0