Introducción a Angular en momentos de cambio

Introducción a angular en momentos de cambio

1. Introducción

Angular está en un momento de cambio. Desde hace algunas versiones se están introduciendo muchos cambios. Mientras escribía este artículo ha salido la versión 18. Quien ya tenga las bases de Angular puede ir asumiendo todos los cambios poco a poco mientras van saliendo. Pero a quien le toque aprender Angular desde cero se le puede hacer un poco difícil entender bien cuál es la manera correcta de hacer las cosas. Personalmente, me tocó aprender Angular cuando justo había salido la versión 17 y me encontré con varias formas para hacer “lo mismo”.

En la documentación está todo explicado, pero, para empezar de cero, la cantidad de información puede llegar a abrumar. Desde mi punto de vista, alguien que se introduce hoy a Angular necesita indagar mucho en la documentación, leer el blog de Angular e incluso leer/ver otros tutoriales para entender bien como se recomienda hacer las cosas, entender la evolución que está teniendo con las últimas novedades y en que estado se encuentran estas novedades exactamente.

En este artículo, haré una introducción a Angular, con la información que a mí me ha sido útil para dar los primeros pasos y entender desde dónde parte Angular y hacia dónde se dirige.

Índice

  1. 1. Introducción
  2. 2. Objetivo del artículo
  3. 3. Diferencias clave respecto a versiones anteriores
    1. 3.1. Rebranding y documentación
    2. 3.2. NgModules vs Standalone APIs
    3. 3.3. Programación reactiva con RxJS vs Signals
    4. 3.4. Decoradores vs Function-based APIs
    5. 3.5. Directivas estructurales vs Built-in control flow blocks
  4. 4. Requisitos previos
  5. 5. ¿Qué es Angular?
  6. 6. Command Line Interface (CLI)
  7. 7. Componentes
    1. 7.1. Estructura
    2. 7.2. Estado y Métodos
      1. 7.2.1. Campos normales
      2. 7.2.2. Estado reactivo con Signals: signal, computed, effect
      3. 7.2.3. Estado reactivo usando RxJS
    3. 7.3. Template
      1. 7.3.1. Renderizar datos dinámicos
      2. 7.3.2. Propiedades y atributos dinámicos
      3. 7.3.3. Event Handling
      4. 7.3.4. Pipes
      5. 7.3.5. Proyección de contenido: Slot y Multi-Slot
    4. 7.4. Styles
    5. 7.5. Inputs: propiedades y atributos dinámicos
    6. 7.6. Outputs: Event Handling
    7. 7.7. Constructor vs Inject
    8. 7.8. Host element
      1. 7.8.1. Estilar el Host element
      2. 7.8.2. Vincular propiedades, atributos y eventos al Host element
  8. 8. Directivas
    1. 8.1. NgClass
    2. 8.2. NgIf
    3. 8.3. Custom directives
  9. 9. Blocks
    1. 9.1. @if
    2. 9.2. @for
    3. 9.3. @switch
    4. 9.4. Deferrable views: @defer
  10. 10. Servicios
  11. 11. Organización
  12. 12. Siguientes pasos
  13. 13. Referencias

2. Objetivo del artículo

El objetivo principal es dar una primera visión de lo que se necesita para empezar en Angular. No explicaré en profundidad cada apartado porque se podría hacer un artículo para cada uno de estos. El objetivo es tener un mapa mental de los principales conceptos de Angular, poniendo lado a lado lo nuevo con lo anterior.

Algo más a tener en cuenta es que explicaré únicamente los cambios que puedan ser más útiles para alguien que recién empieza en Angular. Se están produciendo más cambios, pero desde mi punto de vista se alejan de lo que sería una introducción a Angular.

3. Diferencias clave respecto a versiones anteriores

Hay muchas novedades en Angular en las últimas versiones. En esta sección comentaré las que para mí pueden dar la sensación que hay 2 formas para hacer lo mismo. Si es tu primera introducción a Angular, seguramente esta sección la entenderás mejor después de terminar el turorial.

Antes de empezar, es importante aclarar que varias de las funcionalidades que Angular introduce, primero tienen una fase de Developer Preview y poco a poco se van estabilizando. Esto quiere decir que estas funcionalidades ya están disponibles ser utilizadas, pero que aún podrían tener algún cambio, dependiendo del feedback que reciban de la comunidad.

“This may be because we want to gather feedback from real applications before stabilization, or because the associated documentation or migration tooling is not fully complete.”

3.1. Rebranding y documentación

El primer cambio no es sobre el uso de Angular en sí. Se trata del rebranding y la nueva documentación que salió en la versión 17 y se ha vuelto la web oficial en la versión 18. En estos momentos si buscáis Angular en google aparecen 2 páginas de documentación de Angular: la antigua (angular.io) y la nueva (angular.dev). Con la llegada de la versión 18, la antigua se ha deprecado y redirige a la nueva documentación, aunque aún la podemos visitar si usamos el prefijo v17.

3.2. NgModules vs Standalone APIs

Este cambio es el que menos confusión puede dar actualmente, ya que es el que lleva más tiempo. Antes de la versión 14/15, la manera de organizar una aplicación en Angular era mediante los NgModules, pero en la versión 14 se introdujeron las Standalone APIs en developer preview, en la 15 pasó a ser estable y a partir de la 17 es la forma por defecto en que se generan lo componentes, directivas y pipes. Pero aún hay proyectos en los que no se habrá podido migrar a versiones nuevas y será necesario trabajar con NgModules.

3.3. Programación reactiva con RxJS vs Signals

RxJS es una librería que permite hacer programación reactiva mediante el patrón Observer. RxJS está muy ligado a Angular y no desaparecerá de un día para otro por la llegada de las Signals en la versión 16. Angular está trabajando para que RxJS sea totalmente opcional, pero por ahora aún no es posible. Pero, de momento, sí hay algunos casos en los que las Signals permiten reemplazan el uso de RxJS. Además, hay un paquete de angular para trabajar entre Observables y Signals,

Text
rxjs-interop

.

3.4. Decoradores vs Function-based APIs

Con la llegada de las Signals también llegan las function-based APIs, con las que se reemplazarán muchos decoradores. En la versión 17 se introdujeron en developer preview las

Text
Signal Inputs

,

Text
Signal Model

,

Text
Signal Queries

y la función

Text
output

, la cual no es una Signal, pero permite usarse de la misma forma que el resto.

3.5. Directivas estructurales vs Built-in control flow blocks

Para mejorar la experiencia de desarrollo, se introdujeron en la versión 17, los block template syntax, en developer preview, y en la versión 18 se han estabilizado. De modo que los bloques

Text
@if

,

Text
@switch

y

Text
@for

reemplazan las directivas

Text
*ngIf

Text
*ngSwitch

, y 

Text
*ngFor

.

4. Requisitos previos

Hay algunos requisitos previos a tener en cuenta para poder introducirse a Angular sin más problemas que entender el propio framework:

      • Las bases del frontend: HTML, CSS y JavaScript
      • Las classes en Javascript
      • Las bases de Typescript
      • Los decoradores de Typescript
      • Entender el concepto de componente en el frontend

5. ¿Qué es Angular?

Angular, más allá de un framework, es una plataforma de desarrollo web. Incluye todas las herramientas y librerías necesarias para desarrollar una aplicación web:

      • Un framework de componentes.
      • Librerías para el routing, la gestión de formularios, la comunicación cliente-servidor, el testing, etc.
      • Un CLI para ayudar a la creación, actualización, testing y mantenimiento de las aplicaciones.

Se le pueden añadir y modificar algunas partes en función de lo que se necesite, pero para una introducción sería complicarlo aún más.

6. Command Line Interface (CLI)

Para desarrollar aplicaciones en Angular se recomienda utilizar su CLI. Que te permitirá gestionar un montón de cosas de la aplicación.

Para usarlo, primero necesitamos instalarlo:


Text
npm install -g @angular/cli

Una vez lo tenemos instalado, podemos usar el comando

Text
ng

para ejecutar todos sus comandos. Por ejemplo, podemos crear un proyecto nuevo:


Text
ng new nombre-del-proyecto
cd nombre-del-proyecto

Generar la base de nuevos componentes:


Text
ng generate component ruta-del-componente-(opcional)/nombre-del-componente

O, ejecutar la aplicación:


Text
ng serve

Pero hay muchos otros comandos:

Text
ng build

,

Text
ng test

,

Text
ng e2e

,

Text
ng update

, etc.

7. Componentes

Los componentes son la pieza básica para crear aplicaciones en Angular. Usando el comando

Text
ng generate component nombre-del-componente

se generará un componente con la estructura básica para que lo podamos modificar con nuestras necesidades.

Podemos identificar los componentes en Angular por su sufijo

Text
component

, por ejemplo, si llamamos al componente “item”, el fichero principal del componente sería

Text
item.component.ts

.

7.1. Estructura


Text
@Component({
  selector: 'app-item',
  standalone: true,
  imports: [],
  templateUrl: './item.component.html',
  styleUrl: './item.component.css'
})
export class ItemComponent {
  // Aquí se define el comportamiento del componente
}

La estructura básica de un componente se compone por el decorador para definir configuración específica del component y por la clase para definir su comportamiento.

La configuración básica que tendremos en un componente es la siguiente:

      • El
        Text
        selector

        es el nombre del tag de ese componente. Por ejemplo, si llamamos al selector

        Text
        app-item

        , usaremos el componente como

        Text
        <app-item></app-item>

        en los templates.

      • Si ponemos la propiedad
        Text
        standalone

        a

        Text
        true

        , estaremos configurando el componente como un un standalone component, en lugar de usar la configuración de los NgModules.

      • En el array de
        Text
        imports

        , se declararán todos los módulos, componentes, directivas, etc. que se vayan a usar en ese componente.

      • El template es el HTML de ese componente. Podemos definirlo mediante el campo
        Text
        templateUrl

        , en la que se indicará la url donde esta definido el template, o mediante el campo

        Text
        template

        , en el que se podrá definir directamente el template entre comillas

        Text
        “”

        o comillas invertidas

        Text
        ``

        .

      • Los estilos del componente se pueden definir en uno de estos 3 campos:
        Text
        styleUrl

        ,

        Text
        styleUrls

        o

        Text
        styles

        . La diferencia entre

        Text
        styleUrl

        y

        Text
        styleUrls

        es que al segundo le deberemos pasar un array de urls, permitiendo tener los estilos divididos en distintos archivos. Y en el campo

        Text
        styles

        , podremos definir directamente los estilos en un string o en un array de strings.

7.2. Estado y Métodos

El estado y los métodos es la forma de darle comportamiento a los componentes.

7.2.1. Campos normales

Se puede crear el estado sin usar nada más allá de lo que se define en Typescript.


Text
@Component({...})
export class ItemComponent {
  count = 0;
  doubleCount = 0;

  increment() {
    this.count = this.count + 1;
    this.doubleCount = this.count * 2;
  }
}

7.2.2. Estado reactivo con Signals: signal, computed, effect

También se puede usar las Signals para definir el estado. Están disponibles estas 3 funciones:

Text
signal

,

Text
computed

y

Text
effect

.


Text
@Component({...})
export class ItemComponent {
  count = signal(0)
  doubleCount = computed(() => this.count() * 2)

  constructor() {
    effect(() => {
      console.log(this.count())
    })
  }

  increment() {
    this.count.update(state => state + 1)
  }

  reset() {
    this.count.set(0)
  }
}

7.2.3. Estado reactivo usando RxJS

O se pueden crear estados usando la librería RxJS.


Text
@Component({...})
export class ItemComponent {
  count$ = new BehaviorSubject<number>(0)
  doubleCount$ = this.count$.pipe(map(value => value * 2))

  increment() {
    this.count$.next(this.count$.value + 1)
  }
}

7.3. Template

Cada componente tiene su template. Es el HTML con sintaxis extra añadida por Angular.

7.3.1. Renderizar datos dinámicos

Para renderizar datos dinámicos, hay que usar las llaves

Text
{{ }}

.


Text
<p>{{ count }}</p> <!-- Normal -->
<p>{{ count() }}</p> <!-- Signal -->
<p>{{ count$ | async }}</p> <!-- RxJS -->

7.3.2. Propiedades y atributos dinámicos

Para definir atributos HTML de forma dinámica a algún elemento, se usarán los corchetes

Text
[ ]

. De esta forma, Angular detectará que el valor asignado se debe tratar como si fuera JavaScript, por lo que le podremos asignar algún estado del componente.


Text
<button [disabled]="isDisabled">+</button>

7.3.3. Event Handling

Se pueden vincular event listeners poniendo el nombre del evento entre paréntesis

Text
( )

e invocando un método al otro lado. Además, si se necesita enviar el objeto del evento a la función, Angular proporciona una variable

Text
$event

.


Text
<button (click)="increment()">+</button>
<button (click)="increment($event)">+</button>

7.3.4. Pipes

Algunas veces hace falta modificar al dato que queremos renderizar. Por ejemplo, mostrar las fechas en un formato concreto o el precio de algún producto con el símbolo de la moneda que corresponda. En estos casos Angular proporciona las Pipes, unas funciones que reciben un valor y lo devuelven transformado.

Para usar las Pipes se debe declarar el módulo de la Pipe en el campo

Text
imports

del componente y usar el operador

Text
|

en el template.


Text
<p>
  {{date | date: "d MMMM, y, h:mm a" : undefined : "es"}}
</p>
<p>
  {{price | currency: "EUR" : "symbol" : undefined : "es"}}
</p>

Además de las Pipes que proporciona Angular, se pueden crear Pipes personalizadas para transformaciones propias. Se tendrá que crear una clase que implemente la interfaz

Text
PipeTransform

y que tenga el decorador

Text
@Pipe

.

7.3.5. Proyección de contenido: Slot y Multi-Slot

Alguna vez se necesita crear componentes flexibles y reutilizables, en la que hay una parte del contenido que es el mismo para todos los casos que se reutilice, pero otra parte del contenido cambia según el caso.

Para esto existe el elemento

Text
ng-content

. Con el que se puede crear un slot o múltiples slots para proyectar contenido. Para tener multiples slots hay que definir un atributo

Text
select

para poder indicar qué contenido va en cada slot.


Text
<div>
  <header>
    <h3>Componente con multi ng-content</h3>
  </header>
  <ng-content></ng-content>
  <h4>Question:</h4>
  <ng-content select="[question]"></ng-content>
  <h4>Answer:</h4>
  <ng-content select="[answer]"></ng-content>
</div>

Text
<app-component-with-multi-ng-content>
  <p>Contenido proyectado por defecto</p>
  <p question>¿Cómo puedo proyectar mas de un contenido a la vez?</p>
  <p answer>Con multi-slot content projection!</p>
</app-component-with-multi-ng-content>

7.4. Styles

Lo más importante a tener en cuenta en los estilos de cada componente es que, por defecto, los estilos afectarán únicamente al template del propio componente. De esta forma se limitan los side effects. También se puede definir un fichero global de estilos que apliquen a todos los componentes de la aplicación.

7.5. Inputs: propiedades y atributos dinámicos

Para enviar información de un componente padre a un hijo se pueden declarar propiedades de la clase hijo como inputs. Se puede hacer mediante el decorador

Text
@Input

o mediante las

Text
Signal Inputs

. Y desde el template del componente padre se puede enviar la información al hijo como un atributo dinámico.


Text
@Component({...})
export class ItemComponent {
  // Usando el decorador.
  @Input({ required: true }) title: string = '';
  @Input() subtitle: string = '';

  // Usando Signal inputs. A partir de la v17.1
  title = input.required<string>()
  subtitle = input<string>("")
}

Text
<app-item-parent [title]="Título" [subtitle]="Subtítulo" />

7.6. Outputs: Event Handling

Para enviar información de un componente hijo a un padre se pueden declarar eventos personalizados. Se declara mediante el decorador

Text
@Output

o la función

Text
output

y cuando haya algún cambio se tiene que emitir el evento. Desde el template del componente padre es donde se vincula el evento.


Text
@Component({...})
export class ItemComponent {
  // Usando el decorador.
  @Output() onNameChange = new EventEmitter<string>();
 
  // Usando output function. A partir de la v17.3
  onNameChange = output<string>();

  // Método para lanzar el evento
  updateName(value: string) {
    this.onNameChange.emit(value);
  }
}

Text
<app-item-parent (onNameChanged)="handleNameChange($event)" />

7.7. Constructor vs Inject

Cuando se necesite inyectar algún servicio en el componente deberemos usar el

Text
constructor

o la función

Text
inject

.


Text
@Component({...})
export class ItemComponent {
        // Usando el constructor.
  constructor(private http: HttpClient) {}

        // Usando la función inject. A partir de la v16.
  private http = inject(HttpClient)
}

7.8. Host element

Para crear un componente en Angular hay que especificar un

Text
selector

. Este se usa para poder usar el componente en los templates de otros componentes. Pero, además, se genera un elemento del DOM con ese selector. Este elemento del DOM es el host element de ese componente.

En el siguiente ejemplo

Text
<app-item>

es el host element del componente

Text
ItemComponent

:


Text
@Component({
  selector: 'app-item',
  template: "<h1>App Item</h1>"
})
export class ItemComponent {
  // Aquí se define el comportamiento del componente
}

Text
<!-- Usando el componente en el template de otro componente -->
<app-item></app-item>

Text
<!-- DOM renderizado -->
<app-item>
  <h1>App Item</h1>
</app-item>

7.8.1. Estilar el Host element

El host element se puede estilar, en el fichero css del componente, con el selector

Text
:host

.


Text
:host {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

7.8.2. Vincular propiedades, atributos y eventos al Host element

De la misma forma que se pueden vincular propiedades, atributos y eventos a los elementos de los templates, también se pueden vincular al host element. Para hacerlo hay que usar la propiedad

Text
host

en el decorador

Text
@Component

.


Text
@Component({
  selector: 'app-item',
  host: {
    '[class.small]': "size() === 'small'",
    '[class.big]': "size() === 'big'",
    '(click)': 'handleClick($event)',
  },
})
export class ItemComponent {
  size = input<'small' | 'big'>('small');

  handleClick(event: MouseEvent) {/* ... */}
}

También se pueden usar los decoradores

Text
@HostBinding

y

Text
@HostListener

, pero actualmente se mantienen para compatibilidad con versiones anteriores.

8. Directivas

Las directivas son clases que añaden comportamiento extra a nuestras aplicaciones. Angular proporciona algunas directivas de atributos (NgClass, NgStyle y NgModel) y algunas directivas estructurales (NgIf, NgFor y NgSwitch).

Explicaré una de cada tipo para que veáis como funcionan. En los dos casos se debe declarar el módulo

Text
CommonModule

en la propiedad

Text
imports

del decorador del componente donde se vayan a usar.

8.1. NgClass

Para usar la directiva

Text
NgClass

se debe añadir

Text
[ngClass]

a un elemento del template y así poder declarar una expresión para añadir clases css en función de alguna condición.


Text
<div [ngClass]="isActive ? 'active' : ''">Is active</div>

8.2. NgIf

La directiva

Text
NgIf

permite mostrar o no un elemento en función de alguna condición. Para usarla se debe añadir

Text
*ngIf

al elemento, seguido de la condición.


Text
<div *ngIf="isActive; else isInactive">
  Is active
</div>
<ng-template #isInactive>
  Is inactive
</ng-template>

Pero, con la llegada de los blocks, hay una alternativa más sencilla para conseguir lo mismo.

8.3. Custom directives

Además de las directivas que proporciona Angular también se pueden crear directivas personalizadas. Para crearlas hay que añadir el decorador

Text
@Directive

a la clase. En la documentación podéis ver como crear directivas de atributos o directivas estructurales.

9. Blocks

Los blocks son una nueva sintaxis para los templates en Angular. Aportan grandes funcionalidades con una sintaxis muy simple. Además, no hace falta añadir ningún módulo en los imports de los componentes para poder usarlos.

9.1. @if

El bloque

Text
@if

viene juntamente con el bloque

Text
@else

. Después de usar el bloque

Text
@if

, se pueden usar los bloques

Text
@else if

y

Text
@else

.


Text
@if (isActive) {
  <div>Is active</div>
} @else (isInactive) {
  <div>Is inactive</div>
}

9.2. @for

El bloque

Text
@for

se puede usar junto al bloque

Text
@empty

para mostrar algo en caso de que el listado este vacío.


Text
@for (player of players; track player.id) {
  <player-component/>
} @empty {
  Empty list of players
}

9.3. @switch

El bloque

Text
@switch

se usa juntamente con los bloques

Text
@case

y

Text
@default

.


Text
@switch (role) {
  @case ('player') { <player-component/> }
  @case ('referee') { <referee-component/> }
  @default { <viewer-component/> }
}

9.4. Deferrable views: @defer

Deferrable views, también conocidas como bloques

Text
@defer

, son una potente herramienta que puede utilizarse para reducir el tamaño inicial del bundle de la aplicación o para aplazar la carga de componentes pesados que puede que no se carguen hasta más adelante o incluso no lleguen a renderizarse.

El bloque

Text
@defer

tiene algunos bloques asociados que permiten gestionar diferentes etapas del proceso de carga diferida:

Text
@placeholder

,

Text
@loading

y

Text
@error

. Además, hay múltiples triggers que pueden desencadenar la carga del bloque:

Text
on idle

,

Text
on hover

,

Text
on interaction

, etc.


Text
@defer (on hover) {
  <app-large-component />
} @loading (minimum 2s) {
  <p>Loading...</p>
} @placeholder {
  <p>Pasa el cursor por encima</p>
}

10. Servicios

Los servicios permiten compartir lógica entre componentes. Se componen por un decorador

Text
@Injectable

y una clase para definir el comportamiento deseado.


Text
@Injectable({
  providedIn: 'root',
})
export class CounterService {
  increment(value: number) {
    return value + 1
  }

  decrease(value: number) {
    return value - 1
  }
}

Text
@Component({...})
export class ItemComponent {
  private counterService = inject(CounterService);
}

11. Organización

Angular tiene dos formas de conseguir que los componentes estén disponibles en otros componentes: Standalone Components y NgModules.

Actualmente, se recomienda usar los Standalone Components. A no ser que el proyecto en el que se vaya a trabajar aún use los NgModules, no hace falta aprenderlos en una introducción a Angular.

Como hemos visto en la sección de estructura, para definir un Standalone Component hay que añadir la propiedad

Text
standalone

con el valor a

Text
true

, en el decorador

Text
@Component

. Además, podremos añadir la propiedad

Text
imports

, en la que se añadirán todas las dependencias que usará el componente.

12. Siguientes pasos

Hasta aquí he mostrado por encima los principales conceptos para que puedas introducirte a Angular. Los siguientes pasos que recomendaría para seguir aprendiendo Angular sería: (1) crear una pequeña aplicación de prueba, para ver todos estos conceptos en marcha; (2) leer la documentación oficial para profundizar en cada uno de los conceptos mostrados en el artículo; y (3) estaría atento a las nuevas actualizaciones para ver la evolución día a día.

Además de los conceptos mostrados hay muchos más. Si queréis ir más allá, dejo una lista de algunos conceptos que pueden ser interesantes aprender y encontrareis en la documentación:

      • Component Lifecycle
      • Text
        ng-template

        y

        Text
        ng-container
      • Two-way binding vs model
      • Queries y Signal queries
      • Inyección de dependencias
      • Routing y navegación
      • Formularios
      • HTTP Client
      • Testing
      • Angular SSR
      • Detección de cambios: OnPush vs Default
      • Zoneless
      • Optimización de imágenes en Angular
      • Internacionalización
      • Animaciones en Angular
      • Angular DevTools

13. Referencias

Comentarios

Un comentario

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

He leído y acepto la política de privacidad

Información básica acerca de la protección de datos

  • Responsable: IZERTIS S.A.
  • Finalidad: Envío información de carácter administrativa, técnica, organizativa y/o comercial sobre los productos y servicios sobre los que se nos consulta.
  • Legitimación: Consentimiento del interesado
  • Destinatarios: Otras empresas del Grupo IZERTIS. Encargados del tratamiento.
  • Derechos: Acceso, rectificación, supresión, cancelación, limitación y portabilidad de los datos.
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad

Front-end developer

¿Quieres publicar en Adictos al trabajo?

Te puede interesar

10/06/2025

Iván Suarez Romero

Aprende cómo migrar tu sitio Joomla 3 a Joomla 5 de forma segura, manteniendo el diseño, la funcionalidad y compatibilidad con extensiones. Una guía paso a paso con recomendaciones, imágenes y buenas prácticas para actualizar sin sorpresas.

04/06/2025

Gonzalo Matarrubia González

Descubre qué es Yocto Project, sus ventajas, usos reales en Izertis y cómo crear tu propia distribución Linux para Raspberry Pi paso a paso, de forma sencilla y flexible.

30/05/2025

Roberto José

¿Trabajas con Drupal y SonarQube 9.9? En este artículo exploramos cómo adaptar el análisis estático para evitar falsos positivos, desactivar reglas conflictivas del Quality Profile y delegar el estilo a PHP CodeSniffer. Una guía práctica para mejorar la integración sin depender aún de SonarQube 10.