Angular 17
Angular 17 — eng katta developer experience yangilanishi: yangi control flow (@if, @for, @defer), Signals production-ready va signal-based component API.
Yangi control flow — @if, @for, @switch
Nima bu?
Angular 17 built-in control flow — *ngIf, *ngFor, ngSwitch o'rniga @if, @for, @switch sintaksisi. Template'da to'g'ridan-to'g'ri, @else, @empty, track majburiy. Build vaqtida transform, runtime tezroq, xato xabarlari yaxshiroq. Eski directive'lar hali ishlaydi, lekin yangi kod @ sintaksisi.
Kod misoli
@Component({
template: `
@if (user(); as u) {
<h1>{{ u.name }}</h1>
} @else if (loading()) {
<app-spinner />
} @else {
<p>Foydalanuvchi topilmadi</p>
}
@for (item of items(); track item.id) {
<li>{{ item.name }}</li>
} @empty {
<p>Ro'yxat bo'sh</p>
}
@switch (status()) {
@case ('pending') { <span>Kutilmoqda</span> }
@case ('done') { <span>Tayyor</span> }
@default { <span>Noma'lum</span> }
}
`,
})
export class DashboardComponent {
user = signal<User | null>(null);
loading = signal(true);
items = signal<Item[]>([]);
status = signal<'pending' | 'done'>('pending');
}
Imtihonda
- @for da nima uchun track majburiy?
- *ngIf va @if farqi?
Yodlash uchun
@if/@for/@switch = yangi sintaksis. track = performance. @empty = bo'sh ro'yxat.
@defer — lazy block, triggerlar
Nima bu?
@defer — template blokini lazy yuklash. Component, pipe va bog'liqliklar faqat kerak bo'lganda bundle'dan yuklanadi. Trigger: on viewport (scroll), on idle, on interaction, on hover, on timer, when. Placeholder, loading, error bloklari. Performance va initial bundle kamaytirish.
Kod misoli
@Component({
template: `
@defer (on viewport) {
<app-heavy-chart [data]="chartData()" />
} @placeholder {
<div class="chart-skeleton">Grafik yuklanmoqda...</div>
} @loading (minimum 500ms) {
<app-spinner />
} @error {
<p>Grafik yuklanmadi</p>
}
@defer (on interaction; on hover) {
<app-comments-section />
} @placeholder {
<button>Kommentariyalarni ko'rish</button>
}
@defer (when showAdmin()) {
<app-admin-panel />
}
`,
})
export class AnalyticsPageComponent {
chartData = signal<ChartData[]>([]);
showAdmin = signal(false);
}
Imtihonda
- @defer va loadComponent farqi?
- on viewport trigger qachon ishlatiladi?
Yodlash uchun
@defer = template lazy load. Trigger = qachon yuklash. placeholder/loading/error.
Signals stable — production
Nima bu?
Angular 17 da Signals production-ready deb e'lon qilindi (16 da preview edi). signal, computed, effect, toSignal, toObservable barqaror API. Change detection strategiyasi va kelajakdagi zoneless yo'l uchun asos. Yangi loyihalarda BehaviorSubject o'rniga signal afzal.
Kod misoli
import { Component, signal, computed } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
@Component({ /* ... */ })
export class UserDashboardComponent {
private userService = inject(UserService);
// Observable → Signal
users = toSignal(this.userService.getUsers(), { initialValue: [] as User[] });
selectedId = signal<number | null>(null);
selectedUser = computed(() => {
const id = this.selectedId();
return id ? this.users().find((u) => u.id === id) ?? null : null;
});
selectUser(id: number) {
this.selectedId.set(id);
}
}
Imtihonda
- Signals 16 va 17 da qanday farq?
- toSignal qachon ishlatiladi?
Yodlash uchun
17 = Signals stable/production. toSignal = Observable bridge.
input(), output(), model() signal-based API
Nima bu?
Angular 17.1+ signal-based I/O — @Input() o'rniga input(), @Output() o'rniga output(), two-way binding uchun model(). Required input: input.required(). Transform va alias qo'llab-quvvatlanadi. Change detection bilan yaxshi integratsiya.
Kod misoli
import { Component, input, output, model } from '@angular/core';
@Component({
selector: 'app-counter',
standalone: true,
template: `
<button (click)="decrement()">-</button>
<span>{{ count() }}</span>
<button (click)="increment()">+</button>
`,
})
export class CounterComponent {
count = model(0); // two-way: [(count)]
step = input(1);
maxReached = output<number>();
increment() {
const next = this.count() + this.step();
this.count.set(next);
if (next >= 10) this.maxReached.emit(next);
}
decrement() {
this.count.update((v) => v - this.step());
}
}
// Parent
@Component({
template: `<app-counter [(count)]="total" [step]="2" (maxReached)="onMax($event)" />`,
})
export class ParentComponent {
total = signal(0);
}
Imtihonda
- model() va @Input + @Output farqi?
- input.required() qanday ishlaydi?
Yodlash uchun
input() = @Input; output() = @Output; model() = two-way [( )].
viewChild(), viewChildren() signal queries
Nima bu?
Angular 17 signal queries — @ViewChild o'rniga viewChild(), @ViewChildren o'rniga viewChildren(). Signal qaytaradi — undefined yoki element, reactive. afterNextRender / lifecycle bilan birga zamonaviy DOM access.
Kod misoli
import { Component, viewChild, ElementRef, afterNextRender } from '@angular/core';
@Component({
template: `
<input #searchInput type="text" />
<button #submitBtn>Qidirish</button>
`,
})
export class SearchComponent {
searchInput = viewChild<ElementRef<HTMLInputElement>>('searchInput');
submitBtn = viewChild.required<ElementRef<HTMLButtonElement>>('submitBtn');
constructor() {
afterNextRender(() => {
this.searchInput()?.nativeElement.focus();
});
}
getQuery(): string {
return this.searchInput()?.nativeElement.value ?? '';
}
}
Imtihonda
- viewChild() va @ViewChild farqi?
- viewChild.required() qachon?
Yodlash uchun
viewChild() = signal query. required = majburiy element. afterNextRender = DOM ready.
