Skip to main content Skills Marketplace Descubra e explore skills de IA criadas pela comunidade.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Copiar promptMostrar detalhes do prompt Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
npx skills add https://github.com/BEKO2210/Firstbrain --skill angularO comando permanece em uma só linha. Role horizontalmente para revisá-lo antes de copiar.
Prefere uma cópia local? Baixe os arquivos disponíveis atualmente no SkillsMP.
Baixar Zip Baixando... Ocupações relacionadas SOC
Baseado na classificação ocupacional SOC
Explorador de arquivos
2 arquivos name angular description Modern Angular (v20+) expert with deep knowledge of Signals, Standalone Components, Zoneless applications, SSR/Hydration, and reactive patterns. type skill created 2026-02-27T00:00:00.000Z domain software-development category frontend risk safe source self tags ["skill","software-development","frontend","angular"]
Angular Expert
Master modern Angular development with Signals, Standalone Components, Zoneless applications, SSR/Hydration, and the latest reactive patterns.
When to Use This Skill
Building new Angular applications (v20+)
Implementing Signals-based reactive patterns
Creating Standalone Components and migrating from NgModules
Configuring Zoneless Angular applications
Implementing SSR, prerendering, and hydration
Optimizing Angular performance
Adopting modern Angular patterns and best practices
Do Not Use This Skill When
Migrating from AngularJS (1.x) → use angular-migration skill
Working with legacy Angular apps that cannot upgrade
General TypeScript issues → use typescript-expert skill
Instructions
Assess the Angular version and project structure
Apply modern patterns (Signals, Standalone, Zoneless)
Implement with proper typing and reactivity
Validate with build and tests
Safety
Always test changes in development before production
Gradual migration for existing apps (don't big-bang refactor)
Keep backward compatibility during transitions
Angular Version Timeline
Version Release Key Features Angular 20 Q2 2025 Signals stable, Zoneless stable, Incremental hydration Angular 21 Q4 2025 Signals-first default, Enhanced SSR Angular 22 Q2 2026 Signal Forms, Selectorless components
1. Signals: The New Reactive Primitive
Signals are Angular's fine-grained reactivity system, replacing zone.js-based change detection.
Core Concepts
import { signal, computed, effect } from "@angular/core" ;
const count = signal (0 );
. ( ());
count. ( );
count. ( v + );
doubled = ( () * );
( {
. ( );
});
console
log
count
set
5
update
(v ) =>
1
const
computed
() =>
count
2
effect
() =>
console
log
`Count changed to: ${count()} `
Signal-Based Inputs and Outputs import { Component , input, output, model } from "@angular/core" ;
@Component ({
selector : "app-user-card" ,
standalone : true ,
template : `
<div class="card">
<h3>{{ name() }}</h3>
<span>{{ role() }}</span>
<button (click)="select.emit(id())">Select</button>
</div>
` ,
})
export class UserCardComponent {
id = input.required <string >();
name = input.required <string >();
role = input<string >("User" );
select = output<string >();
isSelected = model (false );
}
Signal Queries (ViewChild/ContentChild) import {
Component ,
viewChild,
viewChildren,
contentChild,
} from "@angular/core" ;
@Component ({
selector : "app-container" ,
standalone : true ,
template : `
<input #searchInput />
<app-item *ngFor="let item of items()" />
` ,
})
export class ContainerComponent {
searchInput = viewChild<ElementRef >("searchInput" );
items = viewChildren (ItemComponent );
projectedContent = contentChild (HeaderDirective );
focusSearch ( ) {
this .searchInput ()?.nativeElement .focus ();
}
}
When to Use Signals vs RxJS Use Case Signals RxJS Local component state ✅ Preferred Overkill Derived/computed values ✅ computed() combineLatest worksSide effects ✅ effect() tap operatorHTTP requests ❌ ✅ HttpClient returns Observable Event streams ❌ ✅ fromEvent, operators Complex async flows ❌ ✅ switchMap, mergeMap
2. Standalone Components Standalone components are self-contained and don't require NgModule declarations.
Creating Standalone Components import { Component } from "@angular/core" ;
import { CommonModule } from "@angular/common" ;
import { RouterLink } from "@angular/router" ;
@Component ({
selector : "app-header" ,
standalone : true ,
imports : [CommonModule , RouterLink ],
template : `
<header>
<a routerLink="/">Home</a>
<a routerLink="/about">About</a>
</header>
` ,
})
export class HeaderComponent {}
Bootstrapping Without NgModule
import { bootstrapApplication } from "@angular/platform-browser" ;
import { provideRouter } from "@angular/router" ;
import { provideHttpClient } from "@angular/common/http" ;
import { AppComponent } from "./app/app.component" ;
import { routes } from "./app/app.routes" ;
bootstrapApplication (AppComponent , {
providers : [provideRouter (routes), provideHttpClient ()],
});
Lazy Loading Standalone Components
import { Routes } from "@angular/router" ;
export const routes : Routes = [
{
path : "dashboard" ,
loadComponent : () =>
import ("./dashboard/dashboard.component" ).then (
(m ) => m.DashboardComponent ,
),
},
{
path : "admin" ,
loadChildren : () =>
import ("./admin/admin.routes" ).then ((m ) => m.ADMIN_ROUTES ),
},
];
3. Zoneless Angular Zoneless applications don't use zone.js, improving performance and debugging.
Enabling Zoneless Mode
import { bootstrapApplication } from "@angular/platform-browser" ;
import { provideZonelessChangeDetection } from "@angular/core" ;
import { AppComponent } from "./app/app.component" ;
bootstrapApplication (AppComponent , {
providers : [provideZonelessChangeDetection ()],
});
Zoneless Component Patterns import { Component , signal, ChangeDetectionStrategy } from "@angular/core" ;
@Component ({
selector : "app-counter" ,
standalone : true ,
changeDetection : ChangeDetectionStrategy .OnPush ,
template : `
<div>Count: {{ count() }}</div>
<button (click)="increment()">+</button>
` ,
})
export class CounterComponent {
count = signal (0 );
increment ( ) {
this .count .update ((v ) => v + 1 );
}
}
Key Zoneless Benefits
Performance : No zone.js patches on async APIs
Debugging : Clean stack traces without zone wrappers
Bundle size : Smaller without zone.js (~15KB savings)
Interoperability : Better with Web Components and micro-frontends
4. Server-Side Rendering & Hydration
SSR Setup with Angular CLI
Hydration Configuration
import { ApplicationConfig } from "@angular/core" ;
import {
provideClientHydration,
withEventReplay,
} from "@angular/platform-browser" ;
export const appConfig : ApplicationConfig = {
providers : [provideClientHydration (withEventReplay ())],
};
Incremental Hydration (v20+) import { Component } from "@angular/core" ;
@Component ({
selector : "app-page" ,
standalone : true ,
template : `
<app-hero />
@defer (hydrate on viewport) {
<app-comments />
}
@defer (hydrate on interaction) {
<app-chat-widget />
}
` ,
})
export class PageComponent {}
Hydration Triggers Trigger When to Use on idleLow-priority, hydrate when browser idle on viewportHydrate when element enters viewport on interactionHydrate on first user interaction on hoverHydrate when user hovers on timer(ms)Hydrate after specified delay
5. Modern Routing Patterns
Functional Route Guards
import { inject } from "@angular/core" ;
import { Router , CanActivateFn } from "@angular/router" ;
import { AuthService } from "./auth.service" ;
export const authGuard : CanActivateFn = (route, state ) => {
const auth = inject (AuthService );
const router = inject (Router );
if (auth.isAuthenticated ()) {
return true ;
}
return router.createUrlTree (["/login" ], {
queryParams : { returnUrl : state.url },
});
};
export const routes : Routes = [
{
path : "dashboard" ,
loadComponent : () => import ("./dashboard.component" ),
canActivate : [authGuard],
},
];
Route-Level Data Resolvers import { inject } from '@angular/core' ;
import { ResolveFn } from '@angular/router' ;
import { UserService } from './user.service' ;
import { User } from './user.model' ;
export const userResolver : ResolveFn <User > = (route ) => {
const userService = inject (UserService );
return userService.getUser (route.paramMap .get ('id' )!);
};
{
path : 'user/:id' ,
loadComponent : () => import ('./user.component' ),
resolve : { user : userResolver }
}
export class UserComponent {
private route = inject (ActivatedRoute );
user = toSignal (this .route .data .pipe (map (d => d['user' ])));
}
6. Dependency Injection Patterns
Modern inject() Function import { Component , inject } from '@angular/core' ;
import { HttpClient } from '@angular/common/http' ;
import { UserService } from './user.service' ;
@Component ({...})
export class UserComponent {
private http = inject (HttpClient );
private userService = inject (UserService );
users = toSignal (this .userService .getUsers ());
}
Injection Tokens for Configuration import { InjectionToken , inject } from "@angular/core" ;
export const API_BASE_URL = new InjectionToken <string >("API_BASE_URL" );
bootstrapApplication (AppComponent , {
providers : [{ provide : API_BASE_URL , useValue : "https://api.example.com" }],
});
@Injectable ({ providedIn : "root" })
export class ApiService {
private baseUrl = inject (API_BASE_URL );
get (endpoint : string ) {
return this .http .get (`${this .baseUrl} /${endpoint} ` );
}
}
7. Component Composition & Reusability
Content Projection (Slots) @Component ({
selector : 'app-card' ,
template : `
<div class="card">
<div class="header">
<!-- Select by attribute -->
<ng-content select="[card-header]"></ng-content>
</div>
<div class="body">
<!-- Default slot -->
<ng-content></ng-content>
</div>
</div>
`
})
export class CardComponent {}
<app-card>
<h3 card-header > Title</h3 >
<p > Body content</p >
</app-card>
Host Directives (Composition)
@Directive ({
standalone : true ,
selector : '[appTooltip]' ,
inputs : ['tooltip' ]
})
export class TooltipDirective { ... }
@Component ({
selector : 'app-button' ,
standalone : true ,
hostDirectives : [
{
directive : TooltipDirective ,
inputs : ['tooltip: title' ]
}
],
template : `<ng-content />`
})
export class ButtonComponent {}
8. State Management Patterns
Signal-Based State Service import { Injectable , signal, computed } from "@angular/core" ;
interface AppState {
user : User | null ;
theme : "light" | "dark" ;
notifications : Notification [];
}
@Injectable ({ providedIn : "root" })
export class StateService {
private _user = signal<User | null >(null );
private _theme = signal<"light" | "dark" >("light" );
private _notifications = signal<Notification []>([]);
readonly user = computed (() => this ._user ());
readonly theme = computed (() => this ._theme ());
readonly notifications = computed (() => this ._notifications ());
readonly unreadCount = computed (
() => this ._notifications ().filter ((n ) => !n.read ).length ,
);
setUser (user : User | null ) {
this ._user .set (user);
}
toggleTheme ( ) {
this ._theme .update ((t ) => (t === "light" ? "dark" : "light" ));
}
addNotification (notification : Notification ) {
this ._notifications .update ((n ) => [...n, notification]);
}
}
Component Store Pattern with Signals import { Injectable , signal, computed, inject } from "@angular/core" ;
import { HttpClient } from "@angular/common/http" ;
import { toSignal } from "@angular/core/rxjs-interop" ;
@Injectable ()
export class ProductStore {
private http = inject (HttpClient );
private _products = signal<Product []>([]);
private _loading = signal (false );
private _filter = signal ("" );
readonly products = computed (() => this ._products ());
readonly loading = computed (() => this ._loading ());
readonly filteredProducts = computed (() => {
const filter = this ._filter ().toLowerCase ();
return this ._products ().filter ((p ) =>
p.name .toLowerCase ().includes (filter),
);
});
loadProducts ( ) {
this ._loading .set (true );
this .http .get <Product []>("/api/products" ).subscribe ({
next : (products ) => {
this ._products .set (products);
this ._loading .set (false );
},
error : () => this ._loading .set (false ),
});
}
setFilter (filter : string ) {
this ._filter .set (filter);
}
}
9. Forms with Signals (Coming in v22+)
Current Reactive Forms import { Component , inject } from "@angular/core" ;
import { FormBuilder , Validators , ReactiveFormsModule } from "@angular/forms" ;
@Component ({
selector : "app-user-form" ,
standalone : true ,
imports : [ReactiveFormsModule ],
template : `
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<input formControlName="name" placeholder="Name" />
<input formControlName="email" type="email" placeholder="Email" />
<button [disabled]="form.invalid">Submit</button>
</form>
` ,
})
export class UserFormComponent {
private fb = inject (FormBuilder );
form = this .fb .group ({
name : ["" , Validators .required ],
email : ["" , [Validators .required , Validators .email ]],
});
onSubmit ( ) {
if (this .form .valid ) {
console .log (this .form .value );
}
}
}
Signal-Aware Form Patterns (Preview)
import { Component , signal } from '@angular/core' ;
@Component ({...})
export class SignalFormComponent {
name = signal ('' );
email = signal ('' );
isValid = computed (() =>
this .name ().length > 0 &&
this .email ().includes ('@' )
);
submit ( ) {
if (this .isValid ()) {
console .log ({ name : this .name (), email : this .email () });
}
}
}
10. Performance Optimization
Change Detection Strategies @Component ({
changeDetection : ChangeDetectionStrategy .OnPush ,
})
Defer Blocks for Lazy Loading @Component ({
template : `
<!-- Immediate loading -->
<app-header />
<!-- Lazy load when visible -->
@defer (on viewport) {
<app-heavy-chart />
} @placeholder {
<div class="skeleton" />
} @loading (minimum 200ms) {
<app-spinner />
} @error {
<p>Failed to load chart</p>
}
`
})
NgOptimizedImage import { NgOptimizedImage } from '@angular/common' ;
@Component ({
imports : [NgOptimizedImage ],
template : `
<img
ngSrc="hero.jpg"
width="800"
height="600"
priority
/>
<img
ngSrc="thumbnail.jpg"
width="200"
height="150"
loading="lazy"
placeholder="blur"
/>
`
})
11. Testing Modern Angular
Testing Signal Components import { ComponentFixture , TestBed } from "@angular/core/testing" ;
import { CounterComponent } from "./counter.component" ;
describe ("CounterComponent" , () => {
let component : CounterComponent ;
let fixture : ComponentFixture <CounterComponent >;
beforeEach (async () => {
await TestBed .configureTestingModule ({
imports : [CounterComponent ],
}).compileComponents ();
fixture = TestBed .createComponent (CounterComponent );
component = fixture.componentInstance ;
fixture.detectChanges ();
});
it ("should increment count" , () => {
expect (component.count ()).toBe (0 );
component.increment ();
expect (component.count ()).toBe (1 );
});
it ("should update DOM on signal change" , () => {
component.count .set (5 );
fixture.detectChanges ();
const el = fixture.nativeElement .querySelector (".count" );
expect (el.textContent ).toContain ("5" );
});
});
Testing with Signal Inputs import { ComponentFixture , TestBed } from "@angular/core/testing" ;
import { ComponentRef } from "@angular/core" ;
import { UserCardComponent } from "./user-card.component" ;
describe ("UserCardComponent" , () => {
let fixture : ComponentFixture <UserCardComponent >;
let componentRef : ComponentRef <UserCardComponent >;
beforeEach (async () => {
await TestBed .configureTestingModule ({
imports : [UserCardComponent ],
}).compileComponents ();
fixture = TestBed .createComponent (UserCardComponent );
componentRef = fixture.componentRef ;
componentRef.setInput ("id" , "123" );
componentRef.setInput ("name" , "John Doe" );
fixture.detectChanges ();
});
it ("should display user name" , () => {
const el = fixture.nativeElement .querySelector ("h3" );
expect (el.textContent ).toContain ("John Doe" );
});
});
Best Practices Summary Pattern ✅ Do ❌ Don't State Use Signals for local state Overuse RxJS for simple state Components Standalone with direct imports Bloated SharedModules Change Detection OnPush + Signals Default CD everywhere Lazy Loading @defer and loadComponentEager load everything DI inject() functionConstructor injection (verbose) Inputs input() signal function@Input() decorator (legacy)Zoneless Enable for new projects Force on legacy without testing
Resources
Common Troubleshooting Issue Solution Signal not updating UI Ensure OnPush + call signal as function count() Hydration mismatch Check server/client content consistency Circular dependency Use inject() with forwardRef Zoneless not detecting changes Trigger via signal updates, not mutations SSR fetch fails Use TransferState or withFetch()
Connections
Domain: [[Software Entwicklung]]
Kategorie: [[Frontend Entwicklung]]
Navigation: [[Skills Uebersicht]], [[Home]]