Hola buenas a todos! Hoy veremos un poco de lo nuevo en Angular 12…¡Esta nueva versión contiene bastantes cambios!
El proyecto Ivy comenzó en 2018 y se lanzó por primera vez en Angular 8, antes de convertirse en el predeterminado en Angular 9. Desde entonces, la mayorÃa de las aplicaciones cambiaron de View Engine, que ahora está oficialmente en desuso. Las nuevas aplicaciones con Angular 12 aún pueden consumir bibliotecas compiladas con View Engine, pero ahora deben ejecutarse con Ivy. El puente entre los compiladores / tiempos de ejecución, se realiza gracias al compilador de compatibilidad Angular"ngcc"
, que seguirá existiendo durante algún tiempo.
En el futuro, las bibliotecas tendrán que publicar una versión de Ivy, y nos desharemos de ella ngcc
. Para ser precisos, las bibliotecas se publicarán como una versión Ivy “parcialmente compilada”, gracias al enlazador angular. La publicación de una versión de View Engine ahora está obsoleta.
Hay una introducción de alto nivel de este tema en el blog de Angular.
Tenga en cuenta que intentar consumir este nuevo formato de biblioteca Ivy en una aplicación de View Engine arrojará un error ( NG6999 ).
Para resumir:
ngcc.
Las bibliotecas que mantenemos ( ngx-valdemort y ngx-speculoos ) están disponibles en el nuevo formato. ¡Significa que ngcc
 los omitirá y su construcción será más rápida que antes!
Después de algunas discusiones sobre el RFC , Angular 12 desaprobó el soporte para IE 11 y lo eliminará en Angular 13.
Se ha lanzado TypeScript v4.2 y Angular ahora lo admite oficialmente. Puede leer la publicación del anuncio en el blog de Microsoft para obtener más información sobre las nuevas funciones de TS.
Tenga en cuenta que Angular 12 elimina el soporte de TS 4.0 y 4.1, por lo que tendrá que actualizar su versión de TS cuando actualice.
Mientras estamos en el tema de dejar de admitir, Angular v12 ya no es compatible con Node v10.
El operador de fusión nula ( ??
) introducido en TS 3.7 ahora se admite en plantillas. Esto nos permite escribir:
<div>{{ user.name ?? 'Anonymous' }}</div>
El compilador de plantillas ahora también realiza un seguimiento de los comentarios HTML. Puede sonar inútil, pero permite que herramientas aprovechen las angular-eslint
. ¡Asà que ahora podemos deshabilitar directamente una advertencia eslint
!
<!-- eslint-disable-next-line @angular-eslint/template/no-any -->
<div>{{ $any(user).name }}</div>
Puede utilizar los validadores min
y max
en un formulario basado en plantillas (con ngModel
). Estos validadores han estado disponibles desde Angular v4.2 tanto en plantillas como en código con Validators.min
y Validators.max
. Pero la versión de la plantilla se revirtió rápidamente, ya que introdujo un cambio importante en una versión menor de Angular. El plan era reintroducirlos en una versión principal posterior, y 4 años después, aquà están. Ahora también puede usarlos en plantillas (prefiero usar ReactiveForms
). Tenga en cuenta que este es un cambio importante, ya que los atributos min
y max
se ignoraron anteriormente y ahora se detectarán como validadores.
<input [(ngModel)]="user.age" min="1" [max]="max" />
Otro cambio en formas es la adición de emitEvent,
opción para la mayorÃa de los métodos que manejan los controles en FormGroup
(Â addControl
, removeControl
, setControl
) y FormArray
(Â push
, insert
, removeAt
, clear
, setControl
). El valor predeterminado es true
para mantener el comportamiento actual, pero ahora puede especificar el valor en false
para que no se emita un valor y un cambio de estado al usar estos métodos. Por ejemplo:
this.userForm.removeControl('login', { emitEvent: false });
// does not emit the new value of `userForm`
Un pequeño cambio en el paquete common/http
con el que estoy contento, es la posibilidad de usar números o booleanos como parámetros HTTP, sin la necesidad de transformarlos en cadenas. Por ejemplo, solÃamos escribir:
// `page` is a number
this.http.get('api/users', { params: { page: `${page}` }})
Ahora podemos escribir:
this.http.get('api/users', { params: { page: page }});
// o mejor aún...
this.http.get('api/users', { params: { page }});
Otro cambio es la introducción de una enumeración llamada que HttpStatusCode
 representa una lista legible por humanos de códigos de estado HTTP:
// the response is a 401
if (response.status === HttpStatusCode.Unauthorized) {
// we redirect to login
this.router.navigateByUrl('/login');
Es probable que nunca se quedará en mi favorita código de estado HTTP 418 embargo: ImATeapot
.
Una caracterÃstica solicitada desde hace mucho tiempo en HttpClient
es la capacidad de almacenar y recuperar metadatos personalizados para solicitudes, especialmente en interceptores. ¡Esto ahora es posible gracias a HttpContext
!
SolÃa ​​ser doloroso dar contexto a un interceptor. La solución alternativa más común fue usar encabezados:
const headers = { 'should-not-handle-error': 'true' };
return this.http.get('/api/users', { headers });
Y luego verifique y elimine este encabezado en el interceptor:
intercept(req: HttpRequest<unknown>, next: HttpHandler) {
// if there is a header specifically asking for not handling the error, we don't handle it
const shouldNotHandleError = req.headers.get('should-not-handle-error');
if (shouldNotHandleError) {
// don't send the header to the server
req.headers.delete('should-not-handle-error');
}
Ahora es más fácil gracias a HttpContext
. El contexto usa un token seguro de tipo ( HttpContextToken
), por lo que puede definir algo como esto en su interceptor:
export const SHOULD_NOT_HANDLE_ERROR = new HttpContextToken<boolean>(() => false);
Y simplifique el interceptor para:
intercept(req: HttpRequest<unknown>, next: HttpHandler) {
// if there is a context specifically asking for not handling the error, we don't handle it
const shouldNotHandleError = req.context.get(SHOULD_NOT_HANDLE_ERROR);
Todos los métodos HTTP se han actualizado para aceptar una nueva context
opción, que es un mapa que puede crear de forma segura mediante el uso del token definido anteriormente:
const context = new HttpContext().set(SHOULD_NOT_HANDLE_ERROR, true);
return this.http.get('/api/users', { context });
Tenga en cuenta que la XhrFactory
clase de nivel superbajo pasó de angular/common/http
 a angular/common
. No se preocupe, una migración automática reescribirá sus importaciones si la está usando durante la ejecución ng update
.
APP_INITIALIZER
es un token especial que puede utilizar para proporcionar funciones que desee ejecutar en la inicialización de la aplicación. Si la función devuelve un Promise
, Angular espera a que se resuelva la promesa para iniciar la aplicación. Ahora también podemos devolver un Observable
en Angular v12, lo cual es útil ya que todo el ecosistema Angular favorece los observables sobre las promesas.
La emitDistinctChangesOnlyDefaultValue
opción para consultas, introducida en v11.2, ahora tiene el valor predeterminado true
(que es un cambio importante). Si no sabe de qué se trata esta opción, consulte nuestra explicación en nuestra publicación de blog sobre Angular v11.2 ?.
El enrutador ofrece una directiva llamada routerLinkActive
 para agregar una clase CSS al enlace si apunta a la URL actual. La directiva acepta una opción para especificar si desea una coincidencia exacta o no:
<a
routerLink="/admin/users"
routerLinkActive="active-link"
[routerLinkActiveOptions]="{ exact: true }">
Users
</a>
Sin exact
embargo true
, la opción era un poco cruda: si , todas las rutas (segmentos de URL) y los parámetros de consulta deben ser iguales, pero el fragmento y los parámetros de la matriz se ignoraron.
V12 introduce angulares más opciones que permiten especificar exactamente lo que desea hacer coincidir con 4 opciones para las 4 partes de la URL multado sintonizado: paths
, queryParams
, matrixParams
y fragment
.
Las opciones queryParams
y matrixParams
pueden recibir el valor exact
, ignored
 o subset
(si desea hacer coincidir parte de los parámetros pero no necesariamente todos), mientras que la paths
opción puede recibir exact
o subset
 y la fragment
opción solo puede recibir exact
o ignored
:
<a
routerLink="/admin/users"
routerLinkActive="active-link"
[routerLinkActiveOptions]="{ paths: 'exact', queryParams: 'subset', matrixParams: 'ignored', fragment: 'ignored' }">
Users
</a>
exact: true
es lo mismo que paths: 'exact', queryParams: 'exact', matrixParams: 'ignored', fragment: 'ignored'
, y exact: false
es lo mismo que paths: 'subset', queryParams: 'subset', matrixParams: 'ignored', fragment: 'ignored'
.
El isActive
método del enrutador ahora también tiene las mismas opciones.
ActivatedRouteSnapshot.fragment
ahora es anulable. Este es un posible cambio importante, por ng update
lo que agregará automáticamente afirmaciones no nulas a su código si lo está usando.
Ahora es posible deshabilitar las animaciones según la información del tiempo de ejecución. Anteriormente, solo podÃamos incluir BrowserAnimationsModule
o el NoopAnimationsModule
 para habilitar / deshabilitar las animaciones.
Ahora es posible usar BrowserAnimationsModule.withConfig({ disableAnimations: true })
.
Angular v12 ofrece una herramienta llamada localize-migrate
para migrar los ID de sus mensajes al nuevo formato (consulte nuestra publicación de blog sobre Angular v11 ). El formato de mensaje heredado ahora está en desuso.
La migración es bastante fácil:
ng extract-i18n --format=legacy-migrate
npx localize-migrate --files=*.xlf --map-file=messages.json
¡Y ahora puede usar el nuevo formato de ID de mensaje!
Ivy Language Service (que alimenta el autocompletado en su IDE) sigue mejorando y ahora está habilitado de forma predeterminada. Escribimos un artÃculo sobre el servicio de idiomas si quieres sumergirte.
Angular v12 elimina el soporte para zone.js v0.10.x, por lo que ahora debe usar al menos v0.11.4.
El ng
objeto al que puede acceder en la consola del navegador obtuvo una nueva ɵsetProfiler
función, disponible incluso en producción.
Puede llamarlo desde la consola de su navegador con una devolución de llamada que se llamará en algunos eventos especÃficos:
Para tener una idea de lo que hace esto, escriba el siguiente código en la consola de su navegador (en una aplicación Angular 12):
ng.ɵsetProfiler((event, value) => {
console.log(event, value)
})
// logs
// 3 - { title: 'App' }
// and a ton of other traces
DeberÃa ver un montón de trazas que indican cuándo se ejecuta la función de plantilla de un componente, cuándo se ejecuta un enlace del ciclo de vida y cuándo se evalúa un controlador de salida. Este generador de perfiles es un poco crudo, por supuesto, pero podemos imaginar que algunas herramientas aprovecharán esto en el futuro y nos darán una retroalimentación precisa sobre cómo se comportan nuestras aplicaciones.
Tenga en cuenta que esta API es privada y experimental, por lo que podrÃa cambiar en el futuro.
Se ha agregado otra función ng
como, llamada getDirectiveMetadata
. Ahora está disponible a lo largo de getComponent
, getInjector
, etc. Permite agarrar la información de una directiva o un componente directamente desde la consola. Nuevamente, esto es un poco crudo, pero probablemente las herramientas lo usarán para analizar una aplicación en ejecución. Puede probarlo en la consola de su navegador:
const userElement = document.querySelector('app-user');
const userComponent = ng.getComponent(userElement);
const userMetadata = ng.getDirectiveMetadata(userComponent)
console.log(userMetadata);
// logs
// { inputs: { userModel: "userModel" }, outputs: {}, changeDetection: 1, encapsulation: 0 }
Actualización: Angular DevTools se anunció unos dÃas después del lanzamiento v12.
¡Todos nuestros materiales ( libro electrónico , capacitación y capacitación en lÃnea ) están actualizados con estos cambios si desea obtener más información!