IslomDevIslomDev
Booster
Imtihon
Booster
Imtihon
  • Angular Intervyu Tayyorgarlik
  • JavaScript / TypeScript

    • JavaScript / TypeScript
    • Asoslar (JavaScript)
    • Asinxronlik
    • Prototip va OOP
    • TypeScript
    • Performance
  • Algoritmlash

    • Algoritmlash
    • Murakkablik tahlili
    • Ma'lumot tuzilmalari
    • Qidiruv va Saralash
    • Algoritmik paradigmalar
    • Amaliy masalalar
  • Angular — Boshlang'ich

    • Angular — Boshlang'ich
    • Component
    • Template
    • Change Detection
    • Advanced Component
  • Angular — Service va DI

    • Angular — Service va DI
    • Service asoslari
    • HTTP
    • Hierarchical DI
    • Advanced DI
    • State management (service)
  • Angular — Versiyalar

    • Angular — Versiyalar
    • Angular 12–13
    • Angular 14
    • Angular 15
    • Angular 16
    • Angular 17
    • Angular 18+
  • Angular — Directive

    • Angular — Directive
    • Built-in Directives
    • Custom Attribute Directive
    • Custom Structural Directive
    • Advanced
  • Angular — RxJS

    • Angular — RxJS
    • Observable asoslari
    • Asosiy operatorlar
    • Higher-order operatorlar
    • Combination operatorlar
    • Subject turlari
    • Xato va xotira
    • Advanced
  • Angular — Pipe

    • Angular — Pipe
    • Built-in Pipes
    • Custom Pipe
    • Performance
  • Angular — Forms

    • Angular — Forms
    • Template-driven Forms
    • Reactive Forms
    • Validators
    • Advanced
  • Angular — NgModule

    • Angular — NgModule
    • NgModule asoslari
    • Module arxitekturasi
    • Lazy Loading
    • Standalone vs NgModule
  • Angular — Sintaksis va Clean Code

    • Angular — Sintaksis va Clean Code
    • Template sintaksisi
    • Angular 17+ yangi sintaksis
    • Komponent arxitekturasi
    • Performance pattern'lar
    • SOLID va Clean Code
    • Testing

Angular 17+ yangi sintaksis

Daraja:

Angular 17 built-in control flow sintaksisini kiritdi: @if, @for, @switch, @defer. Structural directive (*ngIf, *ngFor) o'rniga to'g'ridan-to'g'ri template sintaksisi — o'qish osonroq, build vaqtida optimallashtiriladi va TypeScript bilan yaxshiroq integratsiya.

@if / @else if / @else — *ngIf o'rniga

Middle

Nima bu?

@if shartli render qiladi; @else if va @else zanjirli shartlar. as kalit so'zi bilan shart natijasini lokal o'zgaruvchi sifatida ishlatish mumkin (@if (user(); as u)). *ngIf dan farqi — alohida NgIf import kerak emas, nested shartlar o'qish oson.

Kod misoli

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

type AuthState = 'loading' | 'guest' | 'authenticated';

@Component({
  selector: 'app-auth-banner',
  standalone: true,
  template: `
    @if (authState() === 'loading') {
      <p class="skeleton">Yuklanmoqda...</p>
    } @else if (authState() === 'guest') {
      <a routerLink="/login">Kirish</a>
    } @else {
      @if (user(); as u) {
        <p>Salom, {{ u.name }}!</p>
        @if (u.role === 'admin') {
          <a routerLink="/admin">Admin</a>
        }
      }
    }
  `,
})
export class AuthBannerComponent {
  authState = signal<AuthState>('loading');
  user = signal<{ name: string; role: string } | null>(null);

  ngOnInit(): void {
    setTimeout(() => {
      this.authState.set('authenticated');
      this.user.set({ name: 'Dilnoza', role: 'admin' });
    }, 500);
  }
}
<!-- Klassik *ngIf (hali qo'llab-quvvatlanadi) -->
<div *ngIf="items.length; else empty">...</div>
<ng-template #empty>Ro'yxat bo'sh</ng-template>

<!-- Zamonaviy -->
@if (items.length) {
  <ul>...</ul>
} @else {
  <p>Ro'yxat bo'sh</p>
}

Imtihonda

  • @if (expr; as x) sintaksisi nima qiladi?
  • *ngIf dan @if ga migratsiya qanday amalga oshiriladi (ng generate @angular/core:control-flow)?
  • @else if nechta bo'lishi mumkin?

Yodlash uchun

@if / @else if / @else — *ngIf o'rniga; as — lokal alias.

@for ... track ... @empty — *ngFor o'rniga

Middle

Nima bu?

@for (item of items; track item.id) ro'yxatni render qiladi. track majburiy — DOM node'larni qayta ishlatish uchun unique identifier. @empty — ro'yxat bo'sh bo'lganda ko'rsatiladi. $index, $first, $last, $even, $odd kontekst o'zgaruvchilari mavjud.

Kod misoli

interface Todo {
  id: number;
  title: string;
  done: boolean;
}

@Component({
  selector: 'app-todo-list',
  standalone: true,
  template: `
    <ul>
      @for (todo of todos(); track todo.id; let i = $index) {
        <li [class.done]="todo.done">
          <span>{{ i + 1 }}. {{ todo.title }}</span>
          <button type="button" (click)="toggle(todo.id)">
            {{ todo.done ? 'Bekor' : 'Bajarildi' }}
          </button>
        </li>
      } @empty {
        <li class="empty">Vazifalar yo'q — dam oling ☕</li>
      }
    </ul>
  `,
  styles: [`.done { text-decoration: line-through; opacity: 0.6; }`],
})
export class TodoListComponent {
  todos = signal<Todo[]>([
    { id: 1, title: 'Angular @for o\'rganish', done: false },
    { id: 2, title: 'track ifodasini tushunish', done: true },
  ]);

  toggle(id: number): void {
    this.todos.update((list) =>
      list.map((t) => (t.id === id ? { ...t, done: !t.done } : t))
    );
  }
}
// track expression variantlari
@for (user of users(); track user.id) { ... }
@for (item of items(); track $index) { ... }  // faqat statik ro'yxat uchun
@for (row of rows(); track row.id + row.version) { ... }  // composite key

Imtihonda

  • Nima uchun track majburiy?
  • trackBy (klassik) va track (yangi) farqi?
  • @empty qachon render bo'ladi?

Yodlash uchun

@for ... track id — DOM reuse; @empty — bo'sh holat.

@switch / @case / @default

Middle

Nima bu?

@switch (expr) — qiymatga qarab turli bloklarni render qiladi. @case value — aniq mos kelish; @default — hech biri mos kelmasa. [ngSwitch] / *ngSwitchCase o'rniga sodda sintaksis. Strict equality (===) bilan solishtiriladi.

Kod misoli

type OrderStatus = 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled';

@Component({
  selector: 'app-order-status',
  standalone: true,
  template: `
    @switch (status()) {
      @case ('pending') {
        <span class="badge badge-warn">Kutilmoqda</span>
      }
      @case ('processing') {
        <span class="badge badge-info">Tayyorlanmoqda</span>
      }
      @case ('shipped') {
        <span class="badge badge-primary">Yo'lda</span>
        <p>Tracking: {{ trackingNumber() }}</p>
      }
      @case ('delivered') {
        <span class="badge badge-success">Yetkazildi ✓</span>
      }
      @default {
        <span class="badge badge-error">Noma'lum holat</span>
      }
    }
  `,
})
export class OrderStatusComponent {
  status = signal<OrderStatus>('shipped');
  trackingNumber = signal('TRK-8842-UZ');
}
<!-- Klassik ngSwitch -->
<div [ngSwitch]="status">
  <p *ngSwitchCase="'pending'">Kutilmoqda</p>
  <p *ngSwitchDefault>Boshqa</p>
</div>

Imtihonda

  • @switch qaysi taqqoslashni ishlatadi?
  • Bir nechta @case bir xil blokni qanday ulashadi?
  • @switch va @if/@else if qachon tanlanadi?

Yodlash uchun

@switch → @case / @default; === taqqoslash.

@defer — lazy block (on viewport, on interaction)

MiddleSenior

Nima bu?

@defer blokni lazy yuklaydi — komponent, pipe yoki og'ir template qismi dastlab bundle'ga kirmaydi. Trigger'lar: on idle (browser bo'sh), on viewport (element ko'rinsa), on interaction (click/hover), on hover, on immediate, on timer(2s), when condition. Performance va initial load uchun kuchli vosita.

SSR bilan o'zaro ta'sir: server render qilinganda @defer bloki odatda faqat @placeholderni HTML'ga chiqaradi — asosiy kontent server javobida yo'q. on viewport, on interaction, on hover kabi trigger'lar brauzer/DOM API'ga tayanadi, shuning uchun serverda ishlamaydi — ular faqat client hydration tugagach faollashadi. Bu degani: agar SEO yoki LCP uchun muhim kontent @defer ichiga qo'yilsa, u qidiruv tizimlari va birinchi render'da ko'rinmaydi — noto'g'ri joyda ishlatilsa Core Web Vitals'ni yomonlashtirishi mumkin. Keyingi Angular versiyalarida qo'shilgan incremental hydration bu muammoni qisman yumshatadi — server ayrim defer bloklarini ham oldindan render qilishi mumkin, lekin bu alohida, ixtiyoriy sozlanadigan xususiyat.

Kod misoli

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

@Component({
  selector: 'app-dashboard',
  standalone: true,
  template: `
    <h1>Dashboard</h1>

    <!-- Viewport'ga kirganda yuklash -->
    @defer (on viewport) {
      <app-heavy-chart [data]="chartData" />
    } @placeholder {
      <div class="chart-skeleton">Grafik joyi...</div>
    } @loading (minimum 300ms) {
      <p>Grafik yuklanmoqda...</p>
    }

    <!-- Foydalanuvchi bosganda yuklash -->
    @defer (on interaction) {
      <app-admin-panel />
    } @placeholder {
      <button type="button">Admin panelni ochish</button>
    }

    <!-- Shart bajarilganda -->
    @defer (when isPremium()) {
      <app-premium-features />
    } @placeholder {
      <p>Premium rejimga o'ting</p>
    }
  `,
})
export class DashboardComponent {
  chartData = [{ label: 'Yan', value: 42 }];
  isPremium = () => false;
}
// Alohida fayl — lazy import
@Component({
  selector: 'app-heavy-chart',
  standalone: true,
  template: `<canvas #chart></canvas>`,
})
export class HeavyChartComponent {
  @Input({ required: true }) data!: unknown[];
}

Imtihonda

  • @defer (on viewport) va lazy route farqi?
  • @loading (minimum 300ms) nima uchun kerak?
  • @defer qaysi holatlarda bundle size'ni kamaytiradi?
  • SSR'da @defer ichidagi kontent boshlang'ich HTML javobida bo'ladimi?

Yodlash uchun

@defer — lazy block; trigger: viewport, interaction, when, timer.

@placeholder, @loading, @error — defer bloklar

MiddleSenior

Nima bu?

@defer bilan birga uchta yordamchi blok: @placeholder — yuklanishdan oldin (skeleton, tugma); @loading — yuklanayotganda (spinner); @error — xato bo'lganda (fallback UI). @loading (minimum Xms) — tez yuklanishda miltillashni oldini oladi. @error ichida qayta urinish tugmasi qo'yish mumkin.

Kod misoli

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

@Component({
  selector: 'app-defer-demo',
  standalone: true,
  template: `
    @defer (on viewport) {
      <app-remote-widget [config]="widgetConfig()" />
    } @placeholder (minimum 500ms) {
      <div class="skeleton skeleton-widget" aria-hidden="true"></div>
    } @loading (after 100ms; minimum 400ms) {
      <div class="spinner" role="status">Widget yuklanmoqda...</div>
    } @error {
      <div class="error-panel">
        <p>Widget yuklanmadi.</p>
        <button type="button" (click)="retry()">Qayta urinish</button>
      </div>
    }
  `,
})
export class DeferDemoComponent {
  widgetConfig = signal({ theme: 'dark' });
  private retryCount = 0;

  retry(): void {
    this.retryCount++;
    // Defer qayta trigger — config reference o'zgartirish
    this.widgetConfig.set({ theme: this.retryCount % 2 ? 'light' : 'dark' });
  }
}
// @error — dynamic import xatosi
@Component({
  selector: 'app-remote-widget',
  standalone: true,
  template: `<p>Remote widget ishlayapti</p>`,
})
export class RemoteWidgetComponent {
  @Input({ required: true }) config!: { theme: string };

  constructor() {
    // Simulyatsiya: ba'zi holatlarda xato
    if (Math.random() < 0.01) {
      throw new Error('Network failure');
    }
  }
}

Imtihonda

  • @placeholder (minimum 500ms) va @loading (after 100ms) farqi?
  • @error qachon ishga tushadi?
  • Defer bloklar tartibi va ixtiyoriy/emasligi?

Yodlash uchun

placeholder → oldin; loading → yuklanish; error → xato fallback.

`@defer` Angular 17+ da `@angular/core` ichida — alohida import kerak emas. Og'ir third-party chart/map kutubxonalari uchun ideal.
Prev
Template sintaksisi
Next
Komponent arxitekturasi