{"id":31582820,"url":"https://github.com/devloversteam/angular-interview-questions","last_synced_at":"2026-02-14T23:08:25.792Z","repository":{"id":316391091,"uuid":"1063168860","full_name":"DevLoversTeam/angular-interview-questions","owner":"DevLoversTeam","description":null,"archived":false,"fork":false,"pushed_at":"2025-10-04T08:24:07.000Z","size":210,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-04T09:21:10.537Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DevLoversTeam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"ViktorSvertoka","buy_me_a_coffee":"viktor.svertoka"}},"created_at":"2025-09-24T09:01:04.000Z","updated_at":"2025-10-04T08:24:11.000Z","dependencies_parsed_at":"2025-09-24T11:36:28.039Z","dependency_job_id":null,"html_url":"https://github.com/DevLoversTeam/angular-interview-questions","commit_stats":null,"previous_names":["devloversteam/angular-interview-questions"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DevLoversTeam/angular-interview-questions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevLoversTeam%2Fangular-interview-questions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevLoversTeam%2Fangular-interview-questions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevLoversTeam%2Fangular-interview-questions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevLoversTeam%2Fangular-interview-questions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DevLoversTeam","download_url":"https://codeload.github.com/DevLoversTeam/angular-interview-questions/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevLoversTeam%2Fangular-interview-questions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278532398,"owners_count":26002353,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-05T23:18:34.214Z","updated_at":"2026-02-14T23:08:25.780Z","avatar_url":"https://github.com/DevLoversTeam.png","language":null,"funding_links":["https://github.com/sponsors/ViktorSvertoka","https://buymeacoffee.com/viktor.svertoka"],"categories":[],"sub_categories":[],"readme":"\u003ch1\u003e\n  Angular \u003cimg src=\"./assets/angular.svg\" width=\"40\" height=\"40\" /\u003e\n\u003c/h1\u003e\n\n\u003ch2\u003eНайпопулярніші запитання та відповіді на співбесіді з Angular\u003c/h2\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e1. Що таке Angular та які його ключові можливості?\u003c/summary\u003e\n\n#### Angular\n\n**Angular** - це повноцінний frontend-фреймворк від Google для побудови\nмасштабованих веб-додатків із підтримкою SPA, SSR, SSG та hybrid rendering.\n\nAngular надає структурований підхід до розробки великих застосунків, включаючи\nархітектуру, маршрутизацію, управління станом і продуктивністю \"out of the box\".\n\n#### Ключові можливості сучасного Angular:\n\n- **Component-based architecture** - декларативна побудова UI на основі\n  компонентів.\n\n- **Standalone Components** - можливість створювати застосунки без жорсткої\n  привʼязки до NgModules.\n\n- **Reactivity (Signals + RxJS)** - сучасна реактивна модель для роботи зі\n  станом і асинхронними потоками даних.\n\n- **Template control flow (@if, @for, @switch)** - нативний, оптимізований\n  синтаксис шаблонів.\n\n- **Dependency Injection (DI)** - потужна, tree-shakable система керування\n  залежностями.\n\n- **Routing \u0026 Lazy Loading** - вбудована маршрутизація з підтримкою code\n  splitting.\n\n- **TypeScript-first** - строга типізація та безпечна розробка за замовчуванням.\n\n- **Rendering \u0026 Performance** - оптимізований change detection, підтримка\n  signal-based рендерингу та zoneless архітектури.\n\n**Коротко**\n\nAngular - це повноцінний framework, який покриває більшість потреб\nenterprise-рівня з коробки: від рендерингу та реактивності до маршрутизації, DI\nта оптимізації продуктивності.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e2. Поясни, що таке data-binding в Angular та які є його типи?\u003c/summary\u003e\n\n#### Angular\n\n- Data-binding - це механізм синхронізації даних між компонентом і шаблоном.\n\n#### Типи data-binding в Angular:\n\n1. **Interpolation** - одностороннє відображення даних у HTML:\n\n```HTML\n\u003cp\u003e{{ userName }}\u003c/p\u003e\n```\n\n2. **Property binding** - передача значень у властивості\n   DOM-елементів/компонентів:\n\n```HTML\n\u003cimg [src]=\"avatarUrl\" /\u003e\n```\n\n3. **Event binding** - реакція на події DOM:\n\n```HTML\n\u003cbutton (click)=\"onSave()\"\u003eSave\u003c/button\u003e\n```\n\n4. **Two-way binding** - синхронізація стану між шаблоном і компонентом\n   ([(...)]):\n\n```HTML\n\u003cinput [(ngModel)]=\"email\" /\u003e\n```\n\n**Коротко**\n\nВ Angular доступні 4 основні типи зв’язування даних - interpolation, property\nbinding, event binding, two-way binding.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e3. Опиши архітектуру Angular-додатку.\u003c/summary\u003e\n\n#### Angular\n\n- Архітектура Angular базується на компонентному підході з чітким розділенням\n  відповідальностей.\n\n#### Основні елементи:\n\n- **Компоненти (Standalone)** - будівельні блоки UI, кожен має шаблон, стилі,\n  логіку.\n\n- **Сервіси** - бізнес-логіка, робота з API, збереження стану; надаються через\n  DI.\n\n- **Signals** - сучасний спосіб керування станом і реактивністю.\n\n- **Control flow (@if, @for, @switch)** - керування відображенням у шаблонах.\n\n- **Router** - маршрутизація між екранами без NgModules, з підтримкою lazy\n  loading.\n\n- **Dependency Injection** - інжекція залежностей з різними scope (root,\n  component, environment).\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e4. Що таке компонент в Angular та як він використовується?\u003c/summary\u003e\n\n#### Angular\n\n- Компонент - це основний будівельний блок Angular-додатку, що відповідає за\n  частину UI та пов’язану з нею логіку.\n\n#### Складається з:\n\n- класу (логіка, стан),\n\n- шаблону HTML,\n\n- стилів,\n\n- метаданих (selector, imports тощо).\n\n#### Використання:\n\n```TypeScript\nimport { Component, signal } from '@angular/core';\n\n@Component({\n  selector: 'app-user-card',\n  standalone: true,\n  template: `\n    \u003ch3\u003e{{ name() }}\u003c/h3\u003e\n    \u003cbutton (click)=\"changeName()\"\u003eChange\u003c/button\u003e\n  `\n})\nexport class UserCardComponent {\n  name = signal('Viktor');\n  changeName() {\n    this.name.set('Updated Name');\n  }\n}\n```\n\nУ шаблоні іншого компонента можна підключити:\n\n```HTML\n\u003capp-user-card\u003e\u003c/app-user-card\u003e\n```\n\n**Коротко**\n\nКомпонент = ізольований блок UI + логіка. В Angular він створюється як\nstandalone, без NgModules.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e5. Що таке директиви в Angular та які з них найчастіше використовуються?\u003c/summary\u003e\n\n#### Angular\n\n- Директива - це інструкція для DOM-елемента або компонента, яка змінює його\n  поведінку чи вигляд.\n\n#### Типи директив:\n\n- **Structural** (змінюють DOM):\n\n  -`@if` (новий синтаксис замість `*ngIf`)\n\n  - `@for` (новий синтаксис замість `*ngFor`)\n\n  - `@switch` (альтернатива `*ngSwitch`)\n\n- **Attribute** (змінюють властивості/стилі елемента):\n\n  - `ngClass`\n\n  - `ngStyle`\n\n  - `ngModel`\n\n- **Custom directives** - можна створювати свої для повторного використання\n  логіки.\n\n**Коротко**\n\nДирективи в Angular = спосіб керувати DOM. Найчастіше - `@if`, `@for`,\n`ngClass`, `ngStyle`, `ngModel`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e6. Як створити сервіс в Angular і навіщо його використовують?\u003c/summary\u003e\n\n#### Angular\n\nСервіс - це клас із бізнес-логікою або функціоналом, який не пов’язаний напряму\nз UI.\n\n#### Використовується для:\n\n- повторного використання коду,\n\n- роботи з API,\n\n- керування станом,\n\n- інкапсуляції логіки поза компонентом.\n\n#### Приклад:\n\n```TypeScript\nimport { Injectable, signal } from '@angular/core';\n\n@Injectable({ providedIn: 'root' })\nexport class UserService {\n  userName = signal('Guest');\n\n  setUser(name: string) {\n    this.userName.set(name);\n  }\n}\n```\n\n#### Використання у компоненті:\n\n```TypeScript\nimport { Component, inject } from '@angular/core';\nimport { UserService } from './user.service';\n\n@Component({\n  selector: 'app-header',\n  standalone: true,\n  template: `\u003ch2\u003eWelcome, {{ userService.userName() }}\u003c/h2\u003e`\n})\nexport class HeaderComponent {\n  userService = inject(UserService);\n}\n```\n\n**Коротко**\n\nСервіс створюють через `@Injectable`, а використовують для бізнес-логіки та\nспільного стану між компонентами.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e7. Поясни, що таке dependency injection (DI) в Angular.\u003c/summary\u003e\n\n#### Angular\n\nDependency Injection (DI) - це механізм Angular, який автоматично створює та\nнадає об’єкти (сервіси, токени) компонентам чи іншим сервісам замість ручного\nстворення через new.\n\n#### Навіщо:\n\n- спрощує тестування (можна підмінити залежності mock-ами),\n\n- забезпечує повторне використання сервісів,\n\n- керує життєвим циклом об’єктів (singleton, scoped).\n\n#### Приклад:\n\n```TypeScript\nimport { Injectable } from '@angular/core';\n\n@Injectable({ providedIn: 'root' })\nexport class ApiService {\n  getData() {\n    return ['item1', 'item2'];\n  }\n}\n```\n\n#### Використання у компоненті:\n\n```TypeScript\nimport { Component, inject } from '@angular/core';\nimport { ApiService } from './api.service';\n\n@Component({\n  selector: 'app-list',\n  standalone: true,\n  template: `\u003cli *ngFor=\"let item of data\"\u003e{{ item }}\u003c/li\u003e`\n})\nexport class ListComponent {\n  api = inject(ApiService);\n  data = this.api.getData();\n}\n```\n\n**Коротко**\n\nDI в Angular = автоматичне надання залежностей (наприклад, сервісів) компонентам\nбез `new`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e8. Що таке модуль в Angular і для чого він використовується?\u003c/summary\u003e\n\n#### Angular\n\n- У попередніх версіях Angular (до 15) модулі (NgModule) були обов’язковими для\n  структурування застосунку. В Angular 20 модулі більше не потрібні, оскільки\n  з’явилися standalone components.\n\n#### Проте модулі ще існують і можуть застосовуватись для:\n\n- сумісності зі старим кодом,\n\n- групування функціоналу (напр. Angular Material ще має модулі),\n\n- поступової міграції на standalone API.\n\n#### Приклад старого підходу:\n\n```TypeScript\n@NgModule({\n  declarations: [AppComponent],\n  imports: [BrowserModule],\n  bootstrap: [AppComponent]\n})\nexport class AppModule {}\n```\n\n#### Актуальний підхід (Angular 20, без модуля):\n\n```TypeScript\nbootstrapApplication(AppComponent, {\n  providers: []\n});\n```\n\n**Коротко**\n\nМодулі в Angular зараз - це легасі-інструмент, який замінено на standalone\nкомпоненти. Їхня головна роль сьогодні - лише для підтримки старого коду чи\nбібліотек.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e9. Як обробляти події в Angular?\u003c/summary\u003e\n\n#### Angular\n\nВ Angular події обробляються через event binding, тобто підписку на подію DOM\nабо кастомної події компонента.\n\n#### Синтаксис:\n\n```HTML\n\u003cbutton (click)=\"onClick()\"\u003eClick me\u003c/button\u003e\n```\n\n#### У компоненті:\n\n```ts\nimport { Component } from '@angular/core';\n\n@Component({\n  selector: 'app-button',\n  standalone: true,\n  template: `\u003cbutton (click)=\"onClick()\"\u003eClick me\u003c/button\u003e`,\n})\nexport class ButtonComponent {\n  onClick() {\n    console.log('Button clicked!');\n  }\n}\n```\n\n#### Кастомна подія (для дочірнього компонента):\n\n```TypeScript\nimport { Component, EventEmitter, Output } from '@angular/core';\n\n@Component({\n  selector: 'app-child',\n  standalone: true,\n  template: `\u003cbutton (click)=\"notifyParent()\"\u003eNotify\u003c/button\u003e`\n})\nexport class ChildComponent {\n  @Output() notify = new EventEmitter\u003cstring\u003e();\n  notifyParent() {\n    this.notify.emit('Hello from child');\n  }\n}\n```\n\n#### У батьківському компоненті:\n\n```HTML\n\u003capp-child (notify)=\"onNotify($event)\"\u003e\u003c/app-child\u003e\n```\n\nКоротко: в Angular події обробляються через `(eventName)=\"handler()\"` для DOM та\nчерез `@Output` + `EventEmitter` для кастомних подій.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e10. Що таке двостороннє зв’язування (two-way binding) і як його реалізувати в Angular?\u003c/summary\u003e\n\n#### Angular\n\nДвостороннє зв’язування (two-way binding) - це синхронізація стану між\nкомпонентом і шаблоном, коли:\n\n- зміни в UI оновлюють стан компонента,\n- зміни в компоненті автоматично відображаються в UI.\n\n#### Класичний підхід (ngModel, template-driven forms):\n\n```HTML\n\u003cinput [(ngModel)]=\"name\" /\u003e\n\u003cp\u003eHello, {{ name }}\u003c/p\u003e\n```\n\n```TypeScript\n@Component({\n  selector: 'app-input',\n  standalone: true,\n  template: `\u003cinput [(ngModel)]=\"name\" /\u003e`\n})\nexport class InputComponent {\n  name = 'Evan';\n}\n```\n\n#### Сучасний підхід з Signals (локальний стан):\n\n```TypeScript\nimport { Component, signal } from '@angular/core';\n\n@Component({\n  selector: 'app-input',\n  standalone: true,\n  template: `\n    \u003cinput\n      [value]=\"name()\"\n      (input)=\"name.set($any($event.target).value)\"\n    /\u003e\n    \u003cp\u003eHello, {{ name() }}\u003c/p\u003e\n  `\n})\nexport class InputComponent {\n  name = signal('Evan');\n}\n```\n\nSignals забезпечують реактивність, але two-way binding тут реалізується вручну\nчерез event → set().\n\n#### Two-way binding між компонентами з model():\n\n```TypeScript\nimport { Component, model } from '@angular/core';\n\n@Component({\n  selector: 'app-input',\n  standalone: true,\n  template: `\n    \u003cinput\n      [value]=\"name()\"\n      (input)=\"name.set($any($event.target).value)\"\n    /\u003e\n  `\n})\nexport class InputComponent {\n  name = model('Evan');\n}\n```\n\n```HTML\n\u003capp-input [(name)]=\"userName\"\u003e\u003c/app-input\u003e\n```\n\n**Коротко**\n\n- `ngModel` - legacy two-way binding\n- `signal()` - сучасна реактивність (локальний стан)\n- `model()` - рекомендований спосіб two-way binding у сучасному Angular\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e11. Поясни різницю між компонентом і директивою в Angular?\u003c/summary\u003e\n\n#### Angular\n\n- Компонент\n\n  - це спеціальний тип директиви, який має шаблон (HTML) + стилі + логіку;\n\n  - використовується для створення UI-елементів;\n\n  - приклад: `@Component({ selector: 'app-user', template: '\u003cp\u003eUser\u003c/p\u003e' })`.\n\n- Директива\n\n  - не має власного шаблону;\n\n  - змінює поведінку або вигляд існуючих елементів/компонентів;\n\n  - може бути structural (`@if`, `@for`) або attribute (`ngClass`, `ngStyle`).\n\n#### Приклад кастомної директиви (attribute):\n\n```TypeScript\nimport { Directive, ElementRef, Renderer2 } from '@angular/core';\n\n@Directive({\n  selector: '[highlight]',\n  standalone: true\n})\nexport class HighlightDirective {\n  constructor(el: ElementRef, r: Renderer2) {\n    r.setStyle(el.nativeElement, 'background', 'yellow');\n  }\n}\n```\n\nВикористання у шаблоні:\n\n```HTML\n\u003cp highlight\u003eText with highlight\u003c/p\u003e\n```\n\n**Коротко**\n\nкомпонент = директива + шаблон, а директива = поведінка без власного UI.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e12. Що таке пайпи (Pipes) в Angular та де їх варто використовувати?\u003c/summary\u003e\n\n#### Angular\n\nPipe - це клас, який трансформує дані без зміни їхнього оригінального стану.\nВикористовується у шаблонах для форматування значень.\n\n#### Приклади вбудованих пайпів:\n\n- `date` → форматування дат\n\n- `currency` → вивід валют\n\n- `uppercase` / `lowercase` → зміна регістру\n\n- `async` → робота з Promise / Observable\n\n#### Приклад використання:\n\n```HTML\n\u003cp\u003e{{ today | date:'dd/MM/yyyy' }}\u003c/p\u003e\n\u003cp\u003e{{ price | currency:'USD' }}\u003c/p\u003e\n```\n\n#### Кастомний pipe:\n\n```TypeScript\nimport { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({\n  name: 'exclaim',\n  standalone: true\n})\nexport class ExclaimPipe implements PipeTransform {\n  transform(value: string): string {\n    return value + '!';\n  }\n}\n```\n\nУ шаблоні:\n\n```HTML\n\u003cp\u003e{{ 'Hello' | exclaim }}\u003c/p\u003e\n\u003c!-- Hello! --\u003e\n```\n\n**Коротко**\n\nPipes потрібні для форматування та трансформації даних у шаблоні, щоб не\nзахаращувати логіку компонента.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e13. Як обробляти надсилання форм (form submissions) в Angular?\u003c/summary\u003e\n\n#### Angular\n\n**В Angular є два основні підходи:**\n\n1. **Template-driven forms** (простий варіант, з `ngModel`):\n\n```HTML\n\u003cform #form=\"ngForm\" (ngSubmit)=\"onSubmit(form.value)\"\u003e\n  \u003cinput name=\"email\" [(ngModel)]=\"email\" required /\u003e\n  \u003cbutton type=\"submit\"\u003eSend\u003c/button\u003e\n\u003c/form\u003e\n```\n\n```TypeScript\nonSubmit(value: any) {\n  console.log('Form submitted:', value);\n}\n```\n\n2. **Reactive forms** (рекомендований для складних кейсів):\n\n```TypeScript\nimport { Component } from '@angular/core';\nimport { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\n\n@Component({\n  selector: 'app-login',\n  standalone: true,\n  imports: [ReactiveFormsModule],\n  template: `\n    \u003cform [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\"\u003e\n      \u003cinput formControlName=\"email\" /\u003e\n      \u003cbutton type=\"submit\"\u003eLogin\u003c/button\u003e\n    \u003c/form\u003e\n  `\n})\nexport class LoginComponent {\n  form = new FormGroup({\n    email: new FormControl('')\n  });\n\n  onSubmit() {\n    console.log(this.form.value);\n  }\n}\n```\n\n**Коротко**\n\nФорми в Angular обробляються через (`ngSubmit`) і бувають template-driven та\nreactive. Для простих форм можна брати `ngModel`, для великих і складних -\nreactive forms.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e14. Що таке Angular CLI і для чого його використовують?\u003c/summary\u003e\n\n#### Angular\n\n**Angular CLI** - це офіційний інструмент командного рядка для створення та\nкерування Angular-проєктами.\n\n#### Основні можливості:\n\n- `ng new` → створення нового застосунку\n\n- `ng serve` → локальний дев-сервер з hot reload\n\n- `ng generate (ng g)` → генерація компонентів, сервісів, пайпів, директив\n\n- `ng build` → продакшн-білд з оптимізацією\n\n- `ng test, ng e2e` → запуск тестів\n\n- `ng add` → інтеграція бібліотек (напр. Angular Material)\n\n- `ng update` → оновлення Angular до нової версії\n\nКоротко: Angular CLI = швидкий старт, генерація коду, білд і управління життєвим\nциклом проєкту.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e15. Як виконувати HTTP-запити в Angular за допомогою HttpClient ?\u003c/summary\u003e\n\n#### Angular\n\nВ Angular для роботи з HTTP використовується HttpClient, який надає методи get,\npost, put, delete тощо.\n\n#### Кроки:\n\n1. Імпортувати HttpClientModule у bootstrapApplication.\n\n2. Інжектити HttpClient у сервіс чи компонент.\n\n3. Виконати запит і підписатися (або використовувати async pipe).\n\n#### Приклад сервісу:\n\n```TypeScript\nimport { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\n\n@Injectable({ providedIn: 'root' })\nexport class ApiService {\n  constructor(private http: HttpClient) {}\n\n  getUsers() {\n    return this.http.get('https://jsonplaceholder.typicode.com/users');\n  }\n}\n```\n\n#### Використання у компоненті:\n\n```TypeScript\nimport { Component, inject } from '@angular/core';\nimport { AsyncPipe, NgFor } from '@angular/common';\nimport { ApiService } from './api.service';\n\n@Component({\n  selector: 'app-users',\n  standalone: true,\n  imports: [NgFor, AsyncPipe],\n  template: `\n    \u003cul\u003e\n      \u003cli *ngFor=\"let user of users$ | async\"\u003e{{ user.name }}\u003c/li\u003e\n    \u003c/ul\u003e\n  `\n})\nexport class UsersComponent {\n  api = inject(ApiService);\n  users$ = this.api.getUsers();\n}\n```\n\n**Коротко**\n\nВ Angular 20 HTTP-запити робляться через HttpClient, а результат часто\nобробляється в шаблоні через async pipe.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e16. Як передати дані з батьківського компонента до дочірнього?\u003c/summary\u003e\n\n#### Angular\n\nПередача даних відбувається через input-зв’язування (@Input() декоратор).\nБатьківський компонент передає значення дочірньому через атрибут у шаблоні.\n\n#### Приклад:\n\n**child.component.ts**\n\n```TypeScript\nimport { Component, Input } from '@angular/core';\n\n@Component({\n  selector: 'app-child',\n  standalone: true,\n  template: `\u003cp\u003eMessage: {{ message }}\u003c/p\u003e`\n})\nexport class ChildComponent {\n  @Input() message = '';\n}\n```\n\n**parent.component.ts**\n\n```TypeScript\nimport { Component } from '@angular/core';\nimport { ChildComponent } from './child.component';\n\n@Component({\n  selector: 'app-parent',\n  standalone: true,\n  imports: [ChildComponent],\n  template: `\u003capp-child [message]=\"parentMessage\"\u003e\u003c/app-child\u003e`\n})\nexport class ParentComponent {\n  parentMessage = 'Hello from Parent!';\n}\n```\n\n**Коротко:**\n\n- Дані від батька до дитини передаються через @Input() - це property binding\n  [property]=\"value\".\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e17. Як передати подію або дані від дочірнього компонента до батьківського?\u003c/summary\u003e\n\n#### Angular\n\nДля передачі подій вгору використовується @Output() разом із EventEmitter.\nДочірній компонент «викидає» подію, а батьківський підписується на неї через\n(eventName) у шаблоні.\n\n**child.component.ts**\n\n```TypeScript\nimport { Component, EventEmitter, Output } from '@angular/core';\n\n@Component({\n  selector: 'app-child',\n  standalone: true,\n  template: `\u003cbutton (click)=\"sendMessage()\"\u003eSend\u003c/button\u003e`\n})\nexport class ChildComponent {\n  @Output() message = new EventEmitter\u003cstring\u003e();\n\n  sendMessage() {\n    this.message.emit('Hello from Child!');\n  }\n}\n```\n\n**parent.component.ts**\n\n```TypeScript\nimport { Component } from '@angular/core';\nimport { ChildComponent } from './child.component';\n\n@Component({\n  selector: 'app-parent',\n  standalone: true,\n  imports: [ChildComponent],\n  template: `\u003capp-child (message)=\"onMessage($event)\"\u003e\u003c/app-child\u003e`\n})\nexport class ParentComponent {\n  onMessage(data: string) {\n    console.log('Received from child:', data);\n  }\n}\n```\n\n**Коротко**\n\nПередача даних child → parent відбувається через `@Output()` і\n`(event) binding`. Дитина емітить подію, батько слухає.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e18. Які є життєві цикли (lifecycle hooks) компонентів в Angular і що вони означають?\u003c/summary\u003e\n\n#### Angular\n\nLifecycle hooks - це методи, які Angular викликає на різних етапах «життя»\nкомпонента: створення, оновлення, знищення.\n\n#### Основні хуки Angular:\n\n| Хук                         | Коли викликається                                        | Типове використання                                         |\n| --------------------------- | -------------------------------------------------------- | ----------------------------------------------------------- |\n| **ngOnChanges(changes)**    | Коли змінюються @Input властивості                       | Реакція на зміни вхідних даних від батьківського компонента |\n| **ngOnInit()**              | Один раз після ініціалізації компоненту                  | Ініціалізація даних, запитів до API                         |\n| **ngDoCheck()**             | На кожній зміні (детекції)                               | Кастомна логіка перевірки змін                              |\n| **ngAfterContentInit()**    | Один раз після вставлення контенту (ng-content)          | Робота з проєктованим контентом                             |\n| **ngAfterContentChecked()** | Після кожної перевірки контенту                          | Оновлення після змін у проєктованому контенті               |\n| **ngAfterViewInit()**       | Один раз після ініціалізації view (дочірніх компонентів) | Доступ до елементів через ViewChild/ViewChildren            |\n| **ngAfterViewChecked()**    | Після кожної перевірки view                              | Оновлення DOM після перевірки                               |\n| **ngOnDestroy()**           | Перед знищенням компоненту                               | Очищення підписок, таймерів, ресурсів                       |\n\n#### Приклад:\n\n```TypeScript\nimport { Component, OnInit, OnDestroy } from '@angular/core';\n\n@Component({\n  selector: 'app-demo',\n  standalone: true,\n  template: `\u003cp\u003eLifecycle demo\u003c/p\u003e`\n})\nexport class DemoComponent implements OnInit, OnDestroy {\n  ngOnInit() {\n    console.log('Component initialized');\n  }\n\n  ngOnDestroy() {\n    console.log('Component destroyed');\n  }\n}\n```\n\n**Коротко**\n\nLifecycle hooks - це хуки життєвого циклу компонента, які дають змогу реагувати\nна створення, оновлення та знищення елемента.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e19. Що таке ViewEncapsulation в Angular і для чого воно використовується?\u003c/summary\u003e\n\n#### Angular\n\nViewEncapsulation - це механізм інкапсуляції стилів у Angular, який визначає, як\nCSS компоненту впливає на DOM (чи лише на цей компонент, чи на весь застосунок).\n\n| Тип інкапсуляції         | Опис                                                                          | Особливість                                     |\n| ------------------------ | ----------------------------------------------------------------------------- | ----------------------------------------------- |\n| **Emulated** _(default)_ | Angular імітує поведінку Shadow DOM, додаючи унікальні атрибути до елементів. | Стилі діють лише всередині цього компонента.    |\n| **ShadowDom**            | Використовує нативний Shadow DOM браузера.                                    | Повна ізоляція стилів, немає витоку назовні.    |\n| **None**                 | Без інкапсуляції.                                                             | Стилі поширюються глобально на весь застосунок. |\n\n#### Приклад:\n\n```TypeScript\nimport { Component, ViewEncapsulation } from '@angular/core';\n\n@Component({\n  selector: 'app-example',\n  templateUrl: './example.component.HTML',\n  styleUrls: ['./example.component.css'],\n  encapsulation: ViewEncapsulation.ShadowDom\n})\nexport class ExampleComponent {}\n```\n\n**Коротко:**\n\nViewEncapsulation контролює межі застосування CSS - чи стилі “ізольовані”\nвсередині компонента, чи поширюються глобально. У більшості випадків -\nвикористовується Emulated.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e20. Як застосовувати умовне (conditional) стилювання в Angular-компонентах?\u003c/summary\u003e\n\n#### Angular\n\n- В Angular умовне стилювання реалізується через директиви прив’язки стилів та\n  класів - `ngClass` і `ngStyle`.\n\n| Метод                  | Приклад                                                                 | Опис                                                 |\n| ---------------------- | ----------------------------------------------------------------------- | ---------------------------------------------------- |\n| **[ngClass]**          | `\u003cdiv [ngClass]=\"{ 'active': isActive, 'disabled': !isActive }\"\u003e\u003c/div\u003e` | Додає або забирає CSS-класи залежно від умови.       |\n| **[ngStyle]**          | `\u003cdiv [ngStyle]=\"{ 'color': isActive ? 'green' : 'red' }\"\u003e\u003c/div\u003e`       | Застосовує стилі напряму через об’єкт.               |\n| **Класова прив’язка**  | `\u003cdiv [class.active]=\"isActive\"\u003e\u003c/div\u003e`                                 | Додає клас, якщо умова `true`.                       |\n| **Стильова прив’язка** | `\u003cdiv [style.backgroundColor]=\"isActive ? 'blue' : 'gray'\"\u003e\u003c/div\u003e`      | Змінює конкретний CSS-властивість залежно від умови. |\n\n**Коротко:**\n\nВикористовуй `ngClass` для керування класами та `ngStyle` або `[style.prop]` для\nдинамічних inline-стилів. Це дає повний контроль над виглядом елементів залежно\nвід стану компонента.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e21. У чому різниця між структурними та атрибутними директивами в Angular?\u003c/summary\u003e\n\n#### Angular\n\n- Директиви в Angular бувають структурні та атрибутні, і вони впливають на DOM\n  по-різному.\n\n| Тип директиви               | Опис                                                           | Приклади                                                                        | Вплив на DOM                                                  |\n| --------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------- |\n| **Структурна (Structural)** | Змінює **структуру DOM** - додає, видаляє або змінює елементи. | `*ngIf`, `*ngFor`, `*ngSwitchCase`                                              | Створює або прибирає елементи в дереві DOM.                   |\n| **Атрибутна (Attribute)**   | Змінює **вигляд або поведінку** наявного елемента.             | `ngClass`, `ngStyle`, `ngModel`, кастомні директиви (наприклад, `appHighlight`) | Не змінює структуру DOM, лише властивості або стилі елемента. |\n\n**Коротко:**\n\nСтруктурні директиви керують тим, що є в DOM, атрибутні директиви - тим, як це\nвиглядає або поводиться.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e22. Як створити власну структурну директиву в Angular?\u003c/summary\u003e\n\n#### Angular\n\nСтруктурна директива змінює DOM (додає або видаляє елементи). Щоб створити\nкастомну структурну директиву:\n\n| Крок | Опис                                                                               |\n| ---- | ---------------------------------------------------------------------------------- |\n| 1    | Створити директиву з декоратором `@Directive` і `standalone: true`.                |\n| 2    | Інжектити `TemplateRef` і `ViewContainerRef` для доступу до шаблону та контейнера. |\n| 3    | Створити метод або сеттер, який вирішує, коли вставляти або видаляти шаблон.       |\n| 4    | Використовувати директиву через `*yourDirective` у шаблоні.                        |\n\n#### Приклад кастомної структурної директиви:\n\n```TypeScript\nimport { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';\n\n@Directive({\n  selector: '[appUnless]',\n  standalone: true\n})\nexport class UnlessDirective {\n  constructor(\n    private templateRef: TemplateRef\u003cany\u003e,\n    private viewContainer: ViewContainerRef\n  ) {}\n\n  @Input() set appUnless(condition: boolean) {\n    this.viewContainer.clear();\n    if (!condition) {\n      this.viewContainer.createEmbeddedView(this.templateRef);\n    }\n  }\n}\n```\n\n#### Використання у шаблоні:\n\n```HTML\n\u003cp *appUnless=\"isLoggedIn\"\u003eYou are not logged in!\u003c/p\u003e\n```\n\n**Коротко:**\n\nКастомна структурна директива керує DOM через `ViewContainerRef` і\n`TemplateRef`. Використовується з `*` синтаксисом у шаблоні.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e23. Як зробити сервіс singleton в Angular?\u003c/summary\u003e\n\n#### Angular\n\nУ Angular singleton-сервіс - це сервіс, який створюється лише один раз і\nвикористовується у всьому застосунку. Для цього потрібно вказати, де він\nнадається (provided).\n\n| Спосіб                                      | Приклад                                         | Пояснення                                                                                                     |\n| ------------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |\n| **1. Через `providedIn: 'root'`**           | `@Injectable({ providedIn: 'root' })`           | Найпоширеніший спосіб. Сервіс реєструється в головному інжекторі, створюється один раз для всього застосунку. |\n| **2. Через модуль (deprecated підхід)**     | Додати в `providers` масив модуля (`@NgModule`) | Використовується рідше. Сервіс буде singleton лише в межах цього модуля.                                      |\n| **3. Через компонент (локальний інжектор)** | Додати в `providers` масив компонента           | Сервіс не буде singleton - створюється новий екземпляр для кожного компонента.                                |\n\n#### Приклад:\n\n```TypeScript\nimport { Injectable } from '@angular/core';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class AuthService {\n  private token = '';\n  setToken(t: string) { this.token = t; }\n  getToken() { return this.token; }\n}\n```\n\n**Коротко:**\n\nНайкраща практика - `@Injectable({ providedIn: 'root' })`, бо це гарантує\nsingleton-поведінку і оптимізує tree-shaking.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e24. Як використовувати Observables у сервісах для обміну даними між компонентами?\u003c/summary\u003e\n\n#### Angular\n\nObservables у сервісах дозволяють реактивно ділитися даними між компонентами -\nбез прямої передачі через `@Input()` чи `@Output()`.\n\n| Підхід              | Опис                                                                             | Типовий випадок використання                                 |\n| ------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------ |\n| **Subject**         | Дає змогу як передавати (`next()`), так і підписуватись (`subscribe()`) на дані. | Динамічне оновлення стану між компонентами.                  |\n| **BehaviorSubject** | Зберігає останнє значення, яке автоматично отримують нові підписники.            | Поточний стан (наприклад, авторизація, вибраний користувач). |\n| **ReplaySubject**   | Передає певну кількість останніх значень новим підписникам.                      | Історія подій або кешування даних.                           |\n\n#### Приклад (через BehaviorSubject):\n\n**data.service.ts**\n\n```TypeScript\nimport { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\n@Injectable({ providedIn: 'root' })\nexport class DataService {\n  private messageSource = new BehaviorSubject\u003cstring\u003e('Hello');\n  message$ = this.messageSource.asObservable();\n\n  updateMessage(newMsg: string) {\n    this.messageSource.next(newMsg);\n  }\n}\n```\n\n**component-a.ts**\n\n```TypeScript\n@Component({...})\nexport class ComponentA {\n  constructor(private dataService: DataService) {}\n  sendMessage() {\n    this.dataService.updateMessage('Message from A');\n  }\n}\n```\n\n**component-b.ts**\n\n```TypeScript\n@Component({...})\nexport class ComponentB {\n  message = '';\n  constructor(private dataService: DataService) {\n    this.dataService.message$.subscribe(msg =\u003e this.message = msg);\n  }\n}\n```\n\n**Коротко:**\n\nСервіс з `Subject` або `BehaviorSubject` діє як “shared data channel” - один\nкомпонент надсилає дані, інші підписуються. Це реактивний і чистий спосіб обміну\nстаном між компонентами.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e25. Які існують способи надання (provide) сервісу в Angular і чим вони відрізняються?\u003c/summary\u003e\n\n#### Angular\n\n- У Angular є кілька способів оголосити, де і як створюється сервіс. Від цього\n  залежить область його дії (scope) - чи він буде singleton, чи матиме локальний\n  екземпляр.\n\n| Спосіб                                           | Як реалізується                                    | Область дії                                                         | Коментар                                          |\n| ------------------------------------------------ | -------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------- |\n| **1. `providedIn: 'root'`**                      | У декораторі `@Injectable({ providedIn: 'root' })` | Глобальна (один екземпляр у всьому застосунку)                      | ✅ Найкраща практика. Оптимізується tree-shaking. |\n| **2. `providedIn: 'platform'`**                  | Через `@Injectable({ providedIn: 'platform' })`    | Спільний сервіс між кількома Angular застосунками на одній сторінці | Рідко використовується.                           |\n| **3. `providedIn: 'any'`**                       | Через `@Injectable({ providedIn: 'any' })`         | Новий екземпляр для кожного lazy-loaded модуля                      | Корисно для ізольованих модулів.                  |\n| **4. У `providers` масиві модуля (`@NgModule`)** | Додавання сервісу в `providers`                    | Тільки в межах цього модуля                                         | Використовується в legacy-проєктах.               |\n| **5. У `providers` масиві компонента**           | `providers: [MyService]` у декораторі `@Component` | Новий екземпляр для кожного екземпляра компонента                   | Для локального стану або ізольованої логіки.      |\n\n#### Приклад:\n\n```TypeScript\n@Injectable({\n  providedIn: 'root'\n})\nexport class UserService {}\n```\n\n**або**\n\n```TypeScript\n@Component({\n  selector: 'app-profile',\n  providers: [UserService]\n})\nexport class ProfileComponent {}\n```\n\n**Коротко:**\n\nНайчастіше використовується `providedIn: 'root'` - це дає один спільний\nекземпляр (singleton). Інші способи - для lazy-loading, ізоляції або особливих\nвипадків.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e26. Поясни, що таке providedIn у сервісах Angular і яку роль воно відіграє?\u003c/summary\u003e\n\n#### Angular\n\n- `providedIn` - це параметр у декораторі `@Injectable`, який визначає, де\n  Angular має зареєструвати сервіс у DI (Dependency Injection) системі. Від\n  нього залежить область дії (scope) сервісу та кількість створених екземплярів.\n\n| Значення `providedIn`          | Опис                                                                | Область дії                                | Використання                               |\n| ------------------------------ | ------------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------ |\n| `'root'`                       | Сервіс реєструється у головному інжекторі застосунку.               | Глобальна (singleton у всьому застосунку). | ✅ Найпоширеніший і рекомендований спосіб. |\n| `'platform'`                   | Один інжектор для всієї платформи (кілька Angular app на сторінці). | Спільний між застосунками.                 | Рідкісний випадок використання.            |\n| `'any'`                        | Кожен lazy-loaded модуль отримує власний екземпляр.                 | Локальна для модуля або компонента.        | Для незалежних частин застосунку.          |\n| Клас або модуль (`SomeModule`) | Сервіс буде створено лише в межах цього модуля.                     | Локальна.                                  | Використовується для модульної ізоляції.   |\n\n#### Приклад:\n\n```TypeScript\n@Injectable({\n  providedIn: 'root'\n})\nexport class LoggerService {\n  log(message: string) {\n    console.log(`[LOG]: ${message}`);\n  }\n}\n```\n\n**Коротко:**\n\n`providedIn` визначає, де саме Angular створює сервіс і чи буде він спільним\n(singleton). У більшості випадків використовують `providedIn: 'root'` - це\nпросто, ефективно і підтримує tree-shaking.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e27. Як у Angular використовувати HttpClient для обробки JSON-даних?\u003c/summary\u003e\n\n#### Angular\n\n`HttpClient` - це сервіс Angular для виконання HTTP-запитів. Він автоматично\nперетворює JSON-відповіді в об’єкти JavaScript, тому додаткового парсингу не\nпотрібно.\n\n| Крок | Опис                                                              |\n| ---- | ----------------------------------------------------------------- |\n| 1    | Імпортуй `HttpClientModule` у кореневий або standalone компонент. |\n| 2    | Інжектуй `HttpClient` у сервіс або компонент.                     |\n| 3    | Використовуй методи `get()`, `post()`, `put()`, `delete()` тощо.  |\n| 4    | Angular автоматично обробляє JSON через RxJS `Observable`.        |\n\n#### Приклад:\n\n```TypeScript\nimport { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { Observable } from 'rxjs';\n\nexport interface User {\n  id: number;\n  name: string;\n  email: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class UserService {\n  private apiUrl = 'https://jsonplaceholder.typicode.com/users';\n\n  constructor(private http: HttpClient) {}\n\n  getUsers(): Observable\u003cUser[]\u003e {\n    return this.http.get\u003cUser[]\u003e(this.apiUrl);\n  }\n\n  addUser(user: User): Observable\u003cUser\u003e {\n    return this.http.post\u003cUser\u003e(this.apiUrl, user);\n  }\n}\n```\n\n**component.ts**\n\n```TypeScript\n@Component({...})\nexport class AppComponent {\n  users$ = this.userService.getUsers();\n\n  constructor(private userService: UserService) {}\n}\n```\n\n#### Особливості:\n\n- `HttpClient` автоматично парсить JSON у JS-об’єкти.\n\n- Можна вказати generic тип (`\u003cUser[]\u003e`), щоб отримати типізовану відповідь.\n\n- Повертає Observable, тому можна застосовувати оператори RxJS (`map`,\n  `catchError`, тощо).\n\n**Коротко:**\n\n`HttpClient` - це зручний API для роботи з JSON у Angular. Він типізований,\nреактивний і не потребує ручного `JSON.parse()`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e28. Як обробляти REST API-запити та помилки у сервісах Angular?\u003c/summary\u003e\n\n#### Angular\n\n- REST-запити в Angular виконуються через `HttpClient`, а обробка помилок -\n  через RxJS оператор `catchError`. Усе це зазвичай інкапсулюється в окремому\n  сервісі, щоб компоненти залишалися “чистими”.\n\n| Крок | Опис                                                             |\n| ---- | ---------------------------------------------------------------- |\n| 1    | Створи сервіс (`@Injectable`) і підключи `HttpClient`.           |\n| 2    | Використовуй методи `get()`, `post()`, `put()`, `delete()`.      |\n| 3    | Обгорни запити у `pipe()` з `catchError()` для обробки помилок.  |\n| 4    | Поверни типізований `Observable`, щоб компонент міг підписатися. |\n\n#### Приклад:\n\n```TypeScript\nimport { Injectable } from '@angular/core';\nimport { HttpClient, HttpErrorResponse } from '@angular/common/http';\nimport { catchError, throwError, Observable } from 'rxjs';\n\nexport interface Product {\n  id: number;\n  name: string;\n  price: number;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ProductService {\n  private apiUrl = 'https://api.example.com/products';\n\n  constructor(private http: HttpClient) {}\n\n  getProducts(): Observable\u003cProduct[]\u003e {\n    return this.http.get\u003cProduct[]\u003e(this.apiUrl).pipe(\n      catchError(this.handleError)\n    );\n  }\n\n  addProduct(product: Product): Observable\u003cProduct\u003e {\n    return this.http.post\u003cProduct\u003e(this.apiUrl, product).pipe(\n      catchError(this.handleError)\n    );\n  }\n\n  private handleError(error: HttpErrorResponse) {\n    if (error.status === 0) {\n      console.error('Network error:', error.error);\n    } else {\n      console.error(`API returned code ${error.status}:`, error.error);\n    }\n    return throwError(() =\u003e new Error('Something went wrong; please try again.'));\n  }\n}\n```\n\n#### Пояснення:\n\n- `catchError()` - RxJS оператор для перехоплення помилок.\n\n- `throwError()` - створює новий стрім з помилкою.\n\n- Обробку логіки (`try again`, `notify user`, `log error`) краще робити\n  всередині сервісу, не в компоненті.\n\n**Коротко:**\n\n- REST API виклики обробляються у сервісі через `HttpClient`. Для помилок\n  використовуй `catchError()` у поєднанні з власним `handleError()` методом - це\n  робить код чистим і передбачуваним.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e29. Як налаштовується маршрутизація (routing) в Angular-застосунках?\u003c/summary\u003e\n\n#### Angular\n\nRouting в Angular визначає, який компонент відображається при переході на певний\nURL. Він налаштовується через масив маршрутів і RouterModule (або\n`provideRouter` для standalone API).\n\n| Крок | Опис                                                                                            |\n| ---- | ----------------------------------------------------------------------------------------------- |\n| 1    | Створити масив маршрутів (`Routes[]`), де кожен об’єкт описує шлях і компонент.                 |\n| 2    | Імпортувати `RouterModule.forRoot(routes)` або використати `provideRouter(routes)` у `main.ts`. |\n| 3    | Додати `\u003crouter-outlet\u003e` у шаблон, щоб рендерити активний маршрут.                              |\n| 4    | Використовувати директиви `[routerLink]` для навігації.                                         |\n\n#### Приклад (standalone routing):\n\n**app.routes.ts**\n\n```TypeScript\nimport { Routes } from '@angular/router';\nimport { HomeComponent } from './home.component';\nimport { AboutComponent } from './about.component';\n\nexport const routes: Routes = [\n  { path: '', component: HomeComponent },\n  { path: 'about', component: AboutComponent },\n  { path: '**', redirectTo: '' } // catch-all\n];\n```\n\n**main.ts**\n\n```TypeScript\nimport { bootstrapApplication } from '@angular/platform-browser';\nimport { provideRouter } from '@angular/router';\nimport { AppComponent } from './app.component';\nimport { routes } from './app.routes';\n\nbootstrapApplication(AppComponent, {\n  providers: [provideRouter(routes)]\n});\n```\n\n**app.component.HTML**\n\n```HTML\n\u003cnav\u003e\n  \u003ca routerLink=\"/\"\u003eHome\u003c/a\u003e\n  \u003ca routerLink=\"/about\"\u003eAbout\u003c/a\u003e\n\u003c/nav\u003e\n\n\u003crouter-outlet\u003e\u003c/router-outlet\u003e\n```\n\n#### Додаткові можливості:\n\n- **Route Guards** (`canActivate`, `canDeactivate`) - для захисту маршрутів.\n\n- **Lazy Loading** - динамічне підвантаження модулів або компонентів.\n\n- **Route Parameters** (`:id`) - для передачі динамічних значень у маршруті.\n\n**Коротко:**\n\nМаршрутизація в Angular конфігурується через масив `Routes` і `RouterModule` або\nprovideRouter(). Компоненти рендеряться у `\u003crouter-outlet\u003e`, а переходи\nвиконуються через `[routerLink]`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e30. Як у Angular створити маршрут, який динамічно завантажує модуль лише під час доступу до нього (lazy loading)?\u003c/summary\u003e\n\n#### Angular\n\nТак, у сучасному Angular (v16–20) це робиться через **_lazy loading_** з\nвикористанням динамічного `import()` у файлі маршрутизації. Це дозволяє не\nвключати модуль у основний bundle, а завантажувати його лише при навігації.\n\n#### Приклад:\n\n```TypeScript\n// app.routes.ts (Angular 17+ standalone API)\nimport { Routes } from '@angular/router';\n\nexport const routes: Routes = [\n  {\n    path: 'admin',\n    loadChildren: () =\u003e\n      import('./admin/admin.routes').then(m =\u003e m.ADMIN_ROUTES),\n  },\n];\n```\n\nУ випадку standalone-компонентів:\n\n```TypeScript\n{\n  path: 'dashboard',\n  loadComponent: () =\u003e\n    import('./dashboard/dashboard.component').then(c =\u003e c.DashboardComponent),\n}\n```\n\n**Коротко:**\n\n- `loadChildren` або `loadComponent` використовуються для lazy loading.\n- Модуль/компонент завантажується лише при першому переході на відповідний\n  маршрут.\n- Це оптимізує стартову швидкість застосунку.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e31. Що таке RouterOutlet в Angular і як його використовують?\u003c/summary\u003e\n\n#### Angular\n\n- `\u003crouter-outlet\u003e` - це директива, яка визначає місце у шаблоні, куди Angular\n  підставляє компонент, що відповідає активному маршруту. Вона є “контейнером”\n  для відображення контенту згідно з конфігурацією маршрутизатора.\n\n#### Приклад:\n\n```HTML\n\u003c!-- app.component.HTML --\u003e\n\u003cnav\u003e\n  \u003ca routerLink=\"/home\"\u003eHome\u003c/a\u003e\n  \u003ca routerLink=\"/about\"\u003eAbout\u003c/a\u003e\n\u003c/nav\u003e\n\n\u003crouter-outlet\u003e\u003c/router-outlet\u003e\n```\n\n```TypeScript\n// app.routes.ts\nimport { Routes } from '@angular/router';\nimport { HomeComponent } from './home.component';\nimport { AboutComponent } from './about.component';\n\nexport const routes: Routes = [\n  { path: 'home', component: HomeComponent },\n  { path: 'about', component: AboutComponent },\n];\n```\n\n**Коротко:**\n\n- `RouterOutlet` - точка вставки для компонентів маршруту.\n- Підтримує вкладені маршрути (може бути кілька `router-outlet`).\n- Без нього маршрути не відображаються у DOM.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e32. Як у Angular застосовуються route guards (захисники маршрутів)?\u003c/summary\u003e\n\n#### Angular\n\n- Route guards - це сервіси, які контролюють доступ до маршрутів. Вони\n  реалізують спеціальні інтерфейси (`CanActivate`, `CanDeactivate`, `CanLoad`,\n  `CanMatch`, `Resolve`) і використовуються в конфігурації маршрутизатора.\n\n#### Приклад (CanActivate):\n\n```TypeScript\n// auth.guard.ts\nimport { CanActivateFn } from '@angular/router';\n\nexport const authGuard: CanActivateFn = (route, state) =\u003e {\n  const isLoggedIn = !!localStorage.getItem('token');\n  return isLoggedIn; // або redirectUrl при потребі\n};\n```\n\n```TypeScript\n// app.routes.ts\nexport const routes = [\n  {\n    path: 'dashboard',\n    canActivate: [authGuard],\n    loadComponent: () =\u003e\n      import('./dashboard/dashboard.component').then(c =\u003e c.DashboardComponent),\n  },\n];\n```\n\n**Коротко:**\n\n- Guards перевіряють, чи можна активувати, завантажити або покинути маршрут.\n- Починаючи з Angular 15+, зручно використовувати функціональні guards\n  (`CanActivateFn`) без класів.\n- Повертають `true/false`, `UrlTree`, або `Observable/Promise`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e33. Для чого в Angular використовується ActivatedRoute у маршрутизації?\u003c/summary\u003e\n\n#### Angular\n\n`ActivatedRoute` дає доступ до інформації про поточний активний маршрут, включно\nз параметрами, query-параметрами, фрагментами URL і даними, переданими через\n`data`. Використовується всередині компонентів для отримання контексту маршруту.\n\n#### Приклад:\n\n```TypeScript\nimport { Component, OnInit } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\n\n@Component({\n  selector: 'app-user',\n  template: `\u003cp\u003eUser ID: {{ userId }}\u003c/p\u003e`\n})\nexport class UserComponent implements OnInit {\n  userId!: string;\n\n  constructor(private route: ActivatedRoute) {}\n\n  ngOnInit() {\n    // отримати параметр з URL\n    this.userId = this.route.snapshot.paramMap.get('id')!;\n\n    // або підписка на зміни параметрів\n    this.route.paramMap.subscribe(params =\u003e {\n      this.userId = params.get('id')!;\n    });\n  }\n}\n```\n\n**Коротко:**\n\n- `ActivatedRoute` - доступ до параметрів маршруту, query-параметрів, fragment і\n  data.\n- Потрібен для динамічного завантаження даних залежно від маршруту.\n- Працює як зі snapshot, так і з Observable для реактивного оновлення.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e34. Що таке параметри маршруту в Angular і як до них звертатися?\u003c/summary\u003e\n\n#### Angular\n\nПараметри маршруту - це змінні частини URL, які визначаються у маршрутах та\nдозволяють передавати дані у компонент.\n\n#### Приклад:\n\n```TypeScript\n// app.routes.ts\nimport { Routes } from '@angular/router';\nimport { UserComponent } from './user.component';\n\nexport const routes: Routes = [\n  { path: 'user/:id', component: UserComponent },\n];\n```\n\n```TypeScript\n// user.component.ts\nimport { Component, OnInit } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\n\n@Component({\n  selector: 'app-user',\n  template: `\u003cp\u003eUser ID: {{ userId }}\u003c/p\u003e`\n})\nexport class UserComponent implements OnInit {\n  userId!: string;\n\n  constructor(private route: ActivatedRoute) {}\n\n  ngOnInit() {\n    // Через snapshot (одноразово)\n    this.userId = this.route.snapshot.paramMap.get('id')!;\n\n    // Через Observable (реактивно при зміні маршруту)\n    this.route.paramMap.subscribe(params =\u003e {\n      this.userId = params.get('id')!;\n    });\n  }\n}\n```\n\n**Коротко:**\n\n- Route parameters - частина URL (наприклад, `/user/123` → `id = 123`).\n- Доступ через `ActivatedRoute.snapshot.paramMap` або\n  `ActivatedRoute.paramMap.subscribe()`.\n- Використовуються для динамічного рендерингу контенту.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e35. Як у Angular заздалегідь завантажити дані перед переходом на маршрут (resolve data)?\u003c/summary\u003e\n\n#### Angular\n\nДля цього використовують **_Route Resolver_** - сервіс, який реалізує інтерфейс\n`Resolve\u003cT\u003e`. Angular чекає, поки resolver отримає дані, і передає їх у\nкомпонент через `ActivatedRoute.data`.\n\n#### Приклад:\n\n```TypeScript\n// user.resolver.ts\nimport { Injectable } from '@angular/core';\nimport { Resolve } from '@angular/router';\nimport { UserService } from './user.service';\n\n@Injectable({ providedIn: 'root' })\nexport class UserResolver implements Resolve\u003cany\u003e {\n  constructor(private userService: UserService) {}\n\n  resolve() {\n    return this.userService.getUser(); // може повертати Observable або Promise\n  }\n}\n```\n\n```TypeScript\n// app.routes.ts\nimport { Routes } from '@angular/router';\nimport { UserComponent } from './user.component';\nimport { UserResolver } from './user.resolver';\n\nexport const routes: Routes = [\n  {\n    path: 'user/:id',\n    component: UserComponent,\n    resolve: { userData: UserResolver }\n  }\n];\n```\n\n```TypeScript\n// user.component.ts\nngOnInit() {\n  this.route.data.subscribe(data =\u003e {\n    console.log(data.userData); // доступ до preload-даних\n  });\n}\n```\n\n**Коротко:**\n\n- Resolver завантажує дані перед активацією маршруту.\n- Повертає `Observable`, `Promise` або просте значення.\n- Дані доступні через `ActivatedRoute.data` у компоненті.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e36. Як реалізувати lazy loading модулів або компонентів у Angular?\u003c/summary\u003e\n\n#### Angular\n\nLazy loading дозволяє завантажувати модулі чи компоненти тільки при переході на\nвідповідний маршрут, щоб зменшити початковий розмір bundle.\n\n#### Приклад для модуля (loadChildren):\n\n```TypeScript\n// app.routes.ts\nimport { Routes } from '@angular/router';\n\nexport const routes: Routes = [\n  {\n    path: 'admin',\n    loadChildren: () =\u003e\n      import('./admin/admin.module').then(m =\u003e m.AdminModule),\n  },\n];\n```\n\n#### Приклад для standalone-компонента (loadComponent):\n\n```TypeScript\n{\n  path: 'dashboard',\n  loadComponent: () =\u003e\n    import('./dashboard/dashboard.component').then(c =\u003e c.DashboardComponent),\n}\n```\n\n**Коротко:**\n\n- `loadChildren` - для lazy loading модулів.\n- `loadComponent` - для lazy loading standalone-компонентів (Angular 15+).\n- Підвищує швидкість старту додатку, завантажуючи код лише за потреби.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e37. Поясни різницю між Template-driven та Reactive формами в Angular.\u003c/summary\u003e\n\n#### Angular\n\n- **Template-driven форми** будуються переважно у HTML-шаблоні за допомогою\n  директив (ngModel, ngForm). Вони простіші, підходять для невеликих форм, але\n  менш контрольовані - логіка зосереджена у шаблоні.\n\n- **Reactive форми** створюються в TypeScript-коді за допомогою FormGroup,\n  FormControl, FormBuilder. Вони більш предиктивні, масштабовані й краще\n  підходять для складних форм, валідації та тестування.\n\n#### Приклад:\n\n**Template-driven:**\n\n```HTML\n\u003cform #form=\"ngForm\"\u003e\n  \u003cinput name=\"email\" ngModel required /\u003e\n\u003c/form\u003e\n```\n\n**Reactive:**\n\n```TypeScript\nform = new FormGroup({\n  email: new FormControl('', { nonNullable: true, validators: [Validators.required] })\n});\n```\n\n```HTML\n\u003cform [formGroup]=\"form\"\u003e\n  \u003cinput formControlName=\"email\" /\u003e\n\u003c/form\u003e\n```\n\n**Коротко:**\n\n- Template-driven - декларативний підхід у шаблоні.\n- Reactive - імперативний підхід у коді, з повним контролем над станом форми.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e38. Як виконується валідація користувацького введення у формах Angular?\u003c/summary\u003e\n\n#### Angular\n\nВ Angular є вбудована, кастомна та асинхронна валідація. Валідація визначається\nабо через HTML-атрибути (у Template-driven формах), або через `Validators` у\nReactive формах.\n\n**Reactive форма з валідацією:**\n\n```TypeScript\nform = new FormGroup({\n  email: new FormControl('', {\n    nonNullable: true,\n    validators: [Validators.required, Validators.email]\n  }),\n  password: new FormControl('', {\n    validators: [Validators.required, Validators.minLength(6)]\n  })\n});\n```\n\n**HTML:**\n\n```HTML\n\u003cform [formGroup]=\"form\"\u003e\n  \u003cinput formControlName=\"email\" /\u003e\n  \u003cdiv *ngIf=\"form.controls.email.invalid \u0026\u0026 form.controls.email.touched\"\u003e\n    Invalid email\n  \u003c/div\u003e\n\u003c/form\u003e\n```\n\n**Кастомний валідатор (приклад):**\n\n```TypeScript\nfunction forbiddenNameValidator(control: FormControl) {\n  return control.value === 'admin' ? { forbiddenName: true } : null;\n}\n```\n\n**Асинхронний валідатор (приклад):**\n\n```TypeScript\nfunction emailExistsValidator(service: UserService): AsyncValidatorFn {\n  return control =\u003e service.checkEmail(control.value).pipe(\n    map(exists =\u003e (exists ? { emailTaken: true } : null))\n  );\n}\n```\n\n**Коротко:**\n\n- Використовуємо Validators (built-in або custom).\n- Реактивний підхід дає більше контролю й гнучкості для відображення помилок та\n  асинхронних перевірок.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e39. Як динамічно додавати або видаляти елементи управління (form controls) у Reactive Forms в Angular?\u003c/summary\u003e\n\n#### Angular\n\n- Для динамічної роботи з полями форми використовують `FormArray` або методи\n  `addControl()` / `removeControl()` у `FormGroup`.\n- Це дозволяє створювати або видаляти поля на льоту - наприклад, динамічні\n  списки чи масиви інпутів.\n\n**Приклад із FormArray:**\n\n```TypeScript\nform = new FormGroup({\n  users: new FormArray\u003cFormControl\u003cstring\u003e\u003e([])\n});\n\nget users() {\n  return this.form.get('users') as FormArray;\n}\n\naddUser() {\n  this.users.push(new FormControl('', Validators.required));\n}\n\nremoveUser(index: number) {\n  this.users.removeAt(index);\n}\n```\n\n**HTML:**\n\n```HTML\n\u003cform [formGroup]=\"form\"\u003e\n  \u003cdiv formArrayName=\"users\"\u003e\n    \u003cdiv *ngFor=\"let user of users.controls; let i = index\"\u003e\n      \u003cinput [formControlName]=\"i\" /\u003e\n      \u003cbutton type=\"button\" (click)=\"removeUser(i)\"\u003eRemove\u003c/button\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n  \u003cbutton type=\"button\" (click)=\"addUser()\"\u003eAdd User\u003c/button\u003e\n\u003c/form\u003e\n```\n\n**Коротко:**\n\n- Використовуй FormArray для списків контролів.\n- Використовуй `addControl()` / `removeControl()` у `FormGroup` для динамічних\n  окремих полів.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e40. Що таке FormGroup у Angular і як він працює?\u003c/summary\u003e\n\n#### Angular\n\n- `FormGroup` - це об’єкт, який об’єднує кілька `FormControl` або навіть інших\n  `FormGroup` у єдину структуру. Він дозволяє керувати станом, значеннями та\n  валідацією всієї групи як одного цілого.\n\n**Ключові моменти:**\n\n- `FormGroup` зберігає набір контролів у вигляді об’єкта.\n\n- Дозволяє отримати стан (`valid`, `dirty`, `touched`) або значення (`value`)\n  всієї групи.\n\n- Може мати групову валідацію (на рівні всієї форми).\n\n**Приклад:**\n\n```TypeScript\nform = new FormGroup({ user: new FormGroup({ name: new FormControl('',\nValidators.required), email: new FormControl('', Validators.email) }) });\n```\n\n**HTML:**\n\n```HTML\n\u003cform [formGroup]=\"form\"\u003e\n  \u003cdiv formGroupName=\"user\"\u003e\n    \u003cinput formControlName=\"name\" /\u003e\n    \u003cinput formControlName=\"email\" /\u003e\n  \u003c/div\u003e\n\u003c/form\u003e\n```\n\n**Коротко:**\n\n- `FormGroup` = контейнер для контролів → дає змогу керувати групою полів як\n  єдиним об’єктом (для валідації, оновлення, сабміту).\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e41. Як створити власні (custom) валідатори у формах Angular?\u003c/summary\u003e\n\n#### Angular\n\nКастомний валідатор - це функція, яка приймає `FormControl` або\n`AbstractControl` і повертає об’єкт помилки `{ [key: string]: any }` або `null`,\nякщо помилок немає. Її можна використовувати в Reactive Forms або\nTemplate-driven.\n\n**Синхронний валідатор (приклад):**\n\n```TypeScript\nimport { AbstractControl, ValidationErrors } from '@angular/forms';\n\nexport function forbiddenWordValidator(control: AbstractControl):\nValidationErrors | null { const forbidden = control.value?.toLowerCase() ===\n'admin'; return forbidden ? { forbiddenWord: true } : null; }\n```\n\n**Використання:**\n\n```TypeScript\nform = new FormGroup({ username: new FormControl('', [forbiddenWordValidator])\n});\n```\n\n**Асинхронний валідатор (приклад):**\n\n```TypeScript\nexport function uniqueEmailValidator(service: UserService) {\n  return (control: AbstractControl) =\u003e {\n    return service\n      .checkEmail(control.value)\n      .pipe(map(isTaken =\u003e (isTaken ? { emailTaken: true } : null)));\n  };\n}\n```\n\n**Коротко:**\n\n- Кастомний валідатор - це функція, що повертає `{ errorKey: true }` або `null`.\n- Може бути синхронним або асинхронним (через Observable).\n- Підходить для складної бізнес-логіки, якої немає серед стандартних\n  `Validators`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e42. Поясни, як використовувати formArrayName для роботи з полями форми типу масиву в Angular.\u003c/summary\u003e\n\n#### Angular\n\n- `formArrayName` використовується в шаблоні для прив’язки до `FormArray`\n  усередині Reactive Forms. Це дозволяє відображати та керувати динамічними\n  наборами полів (наприклад, списком телефонів, тегів чи користувачів).\n\n**Приклад:**\n\n```TypeScript\nform = new FormGroup({\n  phones: new FormArray\u003cFormControl\u003cstring\u003e\u003e([\n    new FormControl('', Validators.required)\n  ])\n});\n\nget phones() {\n  return this.form.get('phones') as FormArray;\n}\n\naddPhone() {\n  this.phones.push(new FormControl('', Validators.required));\n}\n\nremovePhone(index: number) {\n  this.phones.removeAt(index);\n}\n```\n\n**HTML:**\n\n```HTML\n\u003cform [formGroup]=\"form\"\u003e\n  \u003cdiv formArrayName=\"phones\"\u003e\n    \u003cdiv *ngFor=\"let phone of phones.controls; let i = index\"\u003e\n      \u003cinput [formControlName]=\"i\" placeholder=\"Phone number\" /\u003e\n      \u003cbutton type=\"button\" (click)=\"removePhone(i)\"\u003eRemove\u003c/button\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\n  \u003cbutton type=\"button\" (click)=\"addPhone()\"\u003eAdd Phone\u003c/button\u003e\n\u003c/form\u003e\n```\n\n**Коротко:**\n\n- `formArrayName` - це директива для доступу до `FormArray` у шаблоні.\n- Кожен елемент масиву - окремий FormControl або FormGroup.\n- Використовується для динамічних форм, де кількість полів може змінюватися.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e43. Як відправити дані форми з Angular-додатку на бекенд-сервіс?\u003c/summary\u003e\n\n#### Angular\n\n- У Angular форма зазвичай відправляється через сервіс, який використовує\n  `HttpClient` для HTTP-запиту (`POST`, `PUT` тощо). Після сабміту зчитують\n  `form.value`, перевіряють `form.valid` і викликають метод сервісу.\n\n**Приклад:**\n\n```TypeScript\n// user.service.ts\n@Injectable({ providedIn: 'root' })\nexport class UserService {\n  constructor(private http: HttpClient) {}\n\n  submitUser(data: any) {\n    return this.http.post('/api/users', data);\n  }\n}\n```\n\n```TypeScript\n// component.ts\nform = new FormGroup({\n  name: new FormControl('', Validators.required),\n  email: new FormControl('', Validators.email)\n});\n\nconstructor(private userService: UserService) {}\n\nonSubmit() {\n  if (this.form.valid) {\n    this.userService.submitUser(this.form.value).subscribe({\n      next: () =\u003e console.log('User saved!'),\n      error: err =\u003e console.error('Error:', err)\n    });\n  }\n}\n```\n\n**HTML:**\n\n```HTML\n\u003cform [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\"\u003e\n  \u003cinput formControlName=\"name\" /\u003e\n  \u003cinput formControlName=\"email\" /\u003e\n  \u003cbutton type=\"submit\"\u003eSave\u003c/button\u003e\n\u003c/form\u003e\n```\n\n**Коротко:**\n\n- Отримуєш `form.value`.\n- Перевіряєш `form.valid`.\n- Відправляєш через `HttpClient` (звичайно через сервіс).\n- Обробляєш відповідь у `subscribe()`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e44. Що таке виявлення змін (change detection) і як його реалізує Angular?\u003c/summary\u003e\n\n#### Angular\n\nВиявлення змін (change detection) - це процес, за допомогою якого Angular\nвизначає, що дані в компоненті змінились, і оновлює відповідні частини UI.\n\n**Як Angular це реалізує:**\n\n- У сучасному Angular механізм базується на **_Signals_** - Angular відслідковує\n  залежності між сигналами та шаблоном і оновлює тільки ті фрагменти DOM, які\n  справді змінились (fine-grained reactivity, без глобального циклу).\n\n- Без **_Signals_** Angular використовує **_Zone.js_**, який перехоплює\n  async-події і запускає перевірку всього дерева компонентів.\n\n- Для ручного контролю можливе використання `ChangeDetectorRef`.\n\n**Коротко:**\n\nAngular 20+ оновлює UI точково через Signals, а старий підхід (Zone.js +\nглобальна перевірка) використовується лише для зворотної сумісності.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e45. Які основні способи оптимізації продуктивності Angular-застосунку?\u003c/summary\u003e\n\n#### Angular\n\n1. **Використання Signals**\n\nFine-grained reactivity → оновлюється тільки та частина DOM, яка залежить від\nсигналу.\n\n2. **Standalone Components**\n\nМенший бандл, швидший старт, немає модульних оверхедів.\n\n3. **Lazy loading та route-level code splitting**\n\nЗавантажувати лише той код, який потрібен на даному маршруті.\n\n4. **OnPush (для legacy компонентів без сигналів)**\n\nЗменшує кількість викликів change detection у старих компонентах.\n\n5. **trackBy у ngFor**\n\nЗапобігає перерендеру списків:\n\n```HTML\n\u003cli *ngFor=\"let item of items; trackBy: trackById\"\u003e\u003c/li\u003e\n```\n\n6. **Оптимізація RxJS**\n\ntakeUntil, shareReplay, уникання непотрібних сабскрипцій.\n\n7. **Async Pipe замість manual subscribe**\n\nЗапобігає memory leaks і зайвим CD-циклами.\n\n8. **Оптимізація шаблону**\n\nМінімізувати важкі обчислення у template (винести в getters або signals).\n\n9. **Preloading strategies**\n\nОптимізує навігацію між маршрутами (наприклад, PreloadAllModules або custom).\n\n10. **Build-level оптимізації**\n\nng build --configuration production\n\nminification, treeshaking, локальні i18n-файли\n\nimage optimization (WebP/AVIF)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e46. Що таке зони (Zones) в Angular і яку роль вони відіграють?\u003c/summary\u003e\n\n#### Angular\n\nЗони (Zone.js) - це механізм, який перехоплює всі асинхронні операції (події,\nтаймери, проміси) і автоматично запускає change detection після їх виконання.\n\n#### Навіщо Angular використовує зони:\n\nЩоб не писати вручну, коли саме оновлювати UI.\n\nБудь-який async виклик → Angular знає, що могли змінитися дані → оновлює вʼю.\n\n#### Як це працює:\n\nZone.js патчить setTimeout, XHR, addEventListener тощо.\n\nПісля завершення async-дії зона викликає Angular change detection.\n\n#### У сучасному Angular 16–20+:\n\nЗони більше не потрібні для реактивного рендерингу (Signals).\n\nЄ режим Noop Zone / Zoneless, де Angular оновлює UI точково без глобального CD.\n\n**Коротко:**\n\nZones - старий механізм для автозапуску change detection. У нових версіях\nAngular його замінює сигнал-базована реактивність.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e47. Як у Angular налаштувати SSR за допомогою Angular Universal\u003c/summary\u003e\n\n#### Angular\n\n1. Увімкнення SSR\n\n```bash\nng add @angular/ssr\n```\n\nАвтоматично створюється сервер, SSR bootstrap і hydration.\n\n2. Bootstrap\n\n**Browser**\n\n```TypeScript\nbootstrapApplication(AppComponent, appConfig);\n```\n\n**Server**\n\n```TypeScript\nexport default () =\u003e\n  bootstrapApplication(AppComponent, appConfig);\n```\n\n3. Hydration\n\n```TypeScript\nprovideClientHydration()\n```\n\nAngular підхоплює HTML, а не рендерить заново.\n\n4. Сервер (Node / Express)\n\n```TypeScript\nrenderApplication(bootstrap, { url, document })\n```\n\n5. SSR-safe код\n\n```TypeScript\nisPlatformBrowser(PLATFORM_ID)\n```\n\nбез window, document напряму\n\n6. Дані\n\n- API викликаємо **на сервері**\n\n- Передаємо в браузер через `TransferState`\n\n- Signals працюють з SSR без проблем\n\n7. Коли використовувати\n\nSEO, швидкий FCP\n\n8. Коли не використовувати\n\nАдмінки, real-time dashboards\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e48. У чому різниця між Ahead-of-Time (AOT) та Just-in-Time (JIT) компіляцією в Angular і коли використовується кожна з них?\u003c/summary\u003e\n\n#### Angular\n\n#### AOT (Ahead-of-Time)\n\n- Компіляція під час білду\n\n- Angular-шаблони → JS до запуску в браузері\n\n- Швидший старт\n\n- Кращий performance\n\n- Менший бандл\n\n- Ранні compile-time помилки\n\n- Безпека (немає runtime compiler)\n\n**Default у production**\n\n#### JIT (Just-in-Time)\n\n- Компіляція в браузері під час виконання\n\n- Потрібен Angular compiler у runtime\n\n- Повільніший старт\n\n- Більший бандл\n\n- Зручно для dev (швидкий rebuild)\n\n**Використовується в dev-режимі**\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e49. Опишіть декоратори, доступні в Angular.\u003c/summary\u003e\n\n#### Angular\n\nAngular використовує TypeScript-декоратори для опису метаданих компонентів,\nдиректив, сервісів та DI.\n\n1. Класові декоратори\n\n**@Component**\n\nОписує UI-компонент.\n\n```TypeScript\n@Component({ selector: 'app-user', standalone: true, template: `{{ name }}` })\nexport class UserComponent { name = 'Viktor'; }\n```\n\n**@Directive**\n\nСтворює кастомну директиву (attribute або structural).\n\n```TypeScript\n@Directive({ selector: '[appHighlight]' }) export class HighlightDirective {}\n```\n\n**@Pipe**\n\nСтворює pipe для трансформації даних у шаблонах.\n\n```TypeScript\n@Pipe({ name: 'uppercase' }) export class UppercasePipe { transform(value:\nstring) { return value.toUpperCase(); } }\n```\n\n**@Injectable**\n\nПозначає клас як сервіс для DI.\n\n```TypeScript\n@Injectable({ providedIn: 'root' }) export class UserService {}\n```\n\n2. Property decorators (взаємодія з шаблоном)\n\n**@Input**\n\nПередача даних у компонент.\n\n```TypeScript\n@Input() title!: string;\n```\n\n**@Output**\n\nПередача подій з компонента.\n\n```TypeScript\n@Output() saved = new EventEmitter\u003cvoid\u003e();\n```\n\n**@HostBinding**\n\nБайндінг до властивостей host-елемента.\n\n```TypeScript\n@HostBinding('class.active') isActive = true;\n```\n\n**@HostListener**\n\nПідписка на події host-елемента.\n\n```TypeScript\n@HostListener('click') onClick() {}\n```\n\n3. Dependency Injection decorators\n\n**@Inject**\n\nЯвна інʼєкція залежності.\n\n```TypeScript\nconstructor(@Inject(API_URL) private apiUrl: string) {}\n```\n\n**@Optional**\n\nЗалежність може бути відсутня.\n\n```TypeScript\nconstructor(@Optional() private logger?: LoggerService) {}\n```\n\n**@Self**, **@SkipSelf**\n\nКонтроль області пошуку залежностей.\n\n```TypeScript\nconstructor(@Self() private control: NgControl) {}\n```\n\n4. View / Content decorators\n\n**@ViewChild** / **@ViewChildren**\n\nДоступ до елементів власного шаблону.\n\n```TypeScript\n@ViewChild('input') input!: ElementRef;\n```\n\n**@ContentChild** / **@ContentChildren**\n\nДоступ до проєктованого контенту (ng-content).\n\n```TypeScript\n@ContentChild(TemplateRef) tpl!: TemplateRef\u003cany\u003e;\n```\n\n5. Стан у Angular 20+\n\n- Декоратори **все ще підтримуються**\n\n- Але часто замінюються:\n\n  - `inject()` замість constructor DI\n\n  - Signals замість `@Input` + `ngOnChanges`\n\n- **Standalone API не скасовує декоратори**, лише спрощує архітектуру\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e50. Як реалізувати анімаційні переходи в Angular-додатку?\u003c/summary\u003e\n\n#### Angular\n\nAngular має вбудовану систему анімацій через `@angular/animations`. У Angular\n20+ використовую `provideAnimations()` у конфігурації:\n\n```TypeScript\n// app.config.ts\nimport { provideAnimations } from '@angular/platform-browser/animations';\n\nexport const appConfig: ApplicationConfig = {\n  providers: [provideAnimations()]\n};\n```\n\n1. Анімація станів компонента\n\n```TypeScript\ntypescriptimport { trigger, state, style, transition, animate } from '@angular/animations';\n\n@Component({\n  template: `\u003cdiv [@openClose]=\"isOpen()\"\u003eContent\u003c/div\u003e`,\n  animations: [\n    trigger('openClose', [\n      state('true', style({ height: '200px', opacity: 1 })),\n      state('false', style({ height: '0px', opacity: 0 })),\n      transition('false \u003c=\u003e true', animate('300ms ease-in-out'))\n    ])\n  ]\n})\nexport class MyComponent {\n  isOpen = signal(false);\n}\n```\n\n2. Анімація роутів\n\n```TypeScript\n// app.component.ts\n@Component({\n  template: `\n    \u003cdiv [@routeAnimations]=\"outlet.activatedRouteData['animation']\"\u003e\n      \u003crouter-outlet #outlet=\"outlet\"\u003e\u003c/router-outlet\u003e\n    \u003c/div\u003e\n  `,\n  animations: [\n    trigger('routeAnimations', [\n      transition('* \u003c=\u003e *', [\n        query(':enter', [style({ opacity: 0 })], { optional: true }),\n        query(':leave', [animate('200ms', style({ opacity: 0 }))], { optional: true }),\n        query(':enter', [animate('300ms', style({ opacity: 1 }))], { optional: true })\n      ])\n    ])\n  ]\n})\n```\n\n3. Анімація списків (stagger)\n\n```TypeScript\nanimations: [\n  trigger('listAnimation', [\n    transition('* =\u003e *', [\n      query(':enter', [\n        style({ opacity: 0, transform: 'translateY(-20px)' }),\n        stagger(100, [\n          animate('300ms', style({ opacity: 1, transform: 'translateY(0)' }))\n        ])\n      ], { optional: true })\n    ])\n  ])\n]\n```\n\n#### Best Practices\n\n- Використовую `transform` та `opacity` для GPU-acceleration\n- `:enter` / `:leave` для появи/зникнення елементів\n- Створюю reusable анімації через `animation()` та `useAnimation()`\n- Відстежую події: `(@trigger.done)=\"onAnimationDone($event)\"`\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e51. Як створюються власні директиви в Angular?\u003c/summary\u003e\n\n#### Angular\n\n1. Типи директив\n\n- **Attribute directive** - змінює поведінку або вигляд елемента приклад:\n  highlight, tooltip\n\n- **Structural directive** - змінює структуру DOM приклад: *ngIf, *ngFor\n\n2. Attribute directive\n\n**Приклад: директива підсвічування**\n\n```TypeScript\nimport { Directive, ElementRef, Input, effect, signal } from '@angular/core';\n\n@Directive({\n  selector: '[appHighlight]',\n  standalone: true,\n})\nexport class HighlightDirective {\n  color = signal('yellow');\n\n  constructor(private el: ElementRef) {\n    effect(() =\u003e {\n      this.el.nativeElement.style.backgroundColor = this.color();\n    });\n  }\n\n  @Input()\n  set appHighlight(value: string) {\n    this.color.set(value);\n  }\n}\n```\n\n**Використання**\n\n```HTML\n\u003cp appHighlight=\"lightblue\"\u003eHighlighted text\u003c/p\u003e\n```\n\n3. Structural directive\n\n**Приклад: кастомний `*appIf`**\n\n```TypeScript\nimport { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';\n\n@Directive({\n  selector: '[appIf]',\n  standalone: true,\n})\nexport class AppIfDirective {\n  constructor(\n    private tpl: TemplateRef\u003cunknown\u003e,\n    private vcr: ViewContainerRef\n  ) {}\n\n  @Input()\n  set appIf(condition: boolean) {\n    this.vcr.clear();\n    if (condition) {\n      this.vcr.createEmbeddedView(this.tpl);\n    }\n  }\n}\n```\n\n**Використання**\n\n```HTML\n\u003cdiv *appIf=\"isVisible\"\u003eVisible content\u003c/div\u003e\n```\n\n4. Best practices\n\n- Використовуйте standalone директиви\n\n- Для реактивності - signals + effect\n\n- Уникайте прямої роботи з DOM (краще Renderer2, якщо потрібно)\n\n- Мінімізуйте side-effects у constructor\n\n- Structural директиви завжди працюють через TemplateRef + ViewContainerRef\n\n**Коротко**\n\nВласні директиви створюються через `@Directive`, бувають attribute та structural\nі в Angular 20+ зазвичай є standalone з реактивністю на signals.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e52. Чи можете ви пояснити використання директив ngClass та ngStyle?\u003c/summary\u003e\n\n#### Angular\n\nВикористання директив `ngClass` та `ngStyle` в Angular\n\n#### `ngClass`\n\nДиректива `ngClass` використовується для **динамічного додавання або видалення\nCSS-класів** на елементі.\n\n#### Основні форми використання\n\n1. Обʼєкт (найпоширеніше)\n\n```HTML\n\u003cdiv [ngClass]=\"{ active: isActive, disabled: isDisabled }\"\u003e\u003c/div\u003e\n```\n\n2. Масив\n\n```HTML\n\u003cdiv [ngClass]=\"['card', isDark ? 'dark' : 'light']\"\u003e\u003c/div\u003e\n```\n\n3. Рядок\n\n```HTML\n\u003cdiv [ngClass]=\"dynamicClass\"\u003e\u003c/div\u003e\n```\n\n#### Best practices\n\n- Використовуйте для умовної стилізації\n\n- Працює ефективно з `ChangeDetectionStrategy.OnPush`\n\n- Добре поєднується з signals\n\n```TypeScript\nisActive = signal(true);\n```\n\n#### `ngStyle`\n\nДиректива `ngStyle` використовується для динамічного задання inline-стилів.\n\n#### Приклад\n\n```HTML\n\u003cdiv [ngStyle]=\"{ color: textColor, fontSize: fontSize + 'px' }\"\u003e\u003c/div\u003e\n```\n\n```TypeScript\ntextColor = 'red';\nfontSize = 16;\n```\n\n#### Best practices\n\n- Використовуйте лише коли стилі не можна описати класами\n\n- Уникайте великої кількості inline-стилів (performance + maintainability)\n\n#### Angular 20+ рекомендації\n\n- Віддавайте перевагу `ngClass`\n\n- Для складної логіки - computed signals\n\n- Для дизайн-систем - класи + CSS variables\n\n#### Коротке резюме\n\n- `ngClass` - для керування CSS-класами,\n- `ngStyle` - для динамічних inline-стилів.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e53. Як ви взаємодієте з DOM безпосередньо за допомогою директив?\u003c/summary\u003e\n\n#### Angular\n\nВзаємодія з DOM за допомогою директив в Angular\n\n#### Основні способи\n\n1. `ElementRef` (обмежено)\n\nДає доступ до нативного DOM-елемента.\n\n```TypeScript\nconstructor(private el: ElementRef) {\n  this.el.nativeElement.focus();\n}\n```\n\n**Недолік:** прямий доступ до DOM Не рекомендовано для SSR та безпеки\n\n2. Renderer2 (рекомендовано)\n\nАбстракція над DOM - безпечна та SSR-friendly.\n\n```TypeScript\nconstructor(\n  private el: ElementRef,\n  private renderer: Renderer2\n) {}\n\nngOnInit() {\n  this.renderer.setStyle(\n    this.el.nativeElement,\n    'background-color',\n    'yellow'\n  );\n}\n```\n\n- Працює з SSR\n- Безпечний (XSS)\n- Кросплатформений\n\n3. @HostBinding Біндінг до властивостей host-елемента.\n\n```TypeScript\n@HostBinding('class.active') isActive = true;\n```\n\n- Чисто\n- Без прямого DOM-доступу\n\n4. @HostListener\n\nПідписка на події host-елемента.\n\n```TypeScript\n@HostListener('mouseenter')\nonHover() {\n  this.isActive = true;\n}\n```\n\n#### Angular 20+ підхід (best practice)\n\n- Уникати nativeElement напряму\n\n- Використовувати Renderer2\n\n- Для стилів і класів - `@HostBinding`\n\n- Для подій - `@HostListener`\n\n- Для реактивності - signals + effect\n\n- Перевіряти платформу (isPlatformBrowser) при роботі з DOM API\n\n**Коротко**\n\nУ Angular взаємодія з DOM у директивах має відбуватись через Renderer2 або\nhost-декоратори, а не через прямий доступ до nativeElement.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e54. Коли слід використовувати Renderer2 і які його переваги?\u003c/summary\u003e\n\n#### Angular\n\nКоли слід використовувати `Renderer2` і які його переваги\n\n#### Коли використовувати `Renderer2`\n\nВикористовуйте `Renderer2`, коли потрібно:\n\n- Динамічно змінювати **стилі**, **класи**, **атрибути**\n- Додавати або видаляти **DOM-елементи**\n- Працювати з **подіями** зсередини директив\n- Забезпечити **SSR-сумісність**\n- Уникнути **XSS-ризиків**\n- Писати **кросплатформений** код (browser / server / web workers)\n\n## Приклад використання\n\n```TypeScript\nimport { Directive, ElementRef, Renderer2 } from '@angular/core';\n\n@Directive({\n  selector: '[appHighlight]',\n  standalone: true,\n})\nexport class HighlightDirective {\n  constructor(\n    private el: ElementRef,\n    private renderer: Renderer2\n  ) {\n    this.renderer.setStyle(\n      this.el.nativeElement,\n      'background-color',\n      'yellow'\n    );\n  }\n}\n```\n\n#### Переваги `Renderer2`\n\n1. Безпека\n\n- Захищає від XSS\n- Не дозволяє небезпечні DOM-операції напряму\n\n2. SSR-friendly\n\n- Працює коректно при Server-Side Rendering\n- Не ламається через відсутність window / document\n\n3. Абстракція над DOM\n\n- Angular вирішує як саме застосувати зміни\n- Підтримує різні платформи\n\n4. Краща підтримка Angular lifecycle\n\n- Інтегрується з change detection\n- Менше побічних ефектів\n\n#### Коли НЕ варто використовувати `Renderer2`\n\n- Для простого керування класами → краще `ngClass`\n- Для обробки подій → краще `@HostListener`\n- Для стилів → `@HostBinding`\n- Для читання значень (read-only) → допустимо `ElementRef`\n\n#### Angular 20+ рекомендації\n\n- Не використовувати nativeElement напряму\n- Renderer2 - стандарт для директив\n- Поєднувати з signals для реактивності\n- Перевіряти платформу при складних DOM-операціях\n\n**Коротко**\n\nRenderer2 - це безпечний, SSR-сумісний та кросплатформений спосіб взаємодії з\nDOM, який слід використовувати замість прямого доступу до nativeElement.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e55. Як створити власний канал в Angular?\u003c/summary\u003e\n\n#### Angular\n\nЯк створити власний Pipe (канал) в Angular\n\n1. Створення pipe\n\nПриклад: простий pipe для форматування імені\n\n```TypeScript\nimport { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({\n  name: 'capitalize',\n  standalone: true,\n})\nexport class CapitalizePipe implements PipeTransform {\n  transform(value: string): string {\n    if (!value) return '';\n    return value[0].toUpperCase() + value.slice(1);\n  }\n}\n```\n\n2. Використання в шаблоні\n\n```HTML\n\u003cp\u003e{{ 'angular' | capitalize }}\u003c/p\u003e\n```\n\n3. Pure vs Impure pipes\n\n**Pure pipe (за замовчуванням)**\n\n- Викликається лише при зміні input\n\n- Краща продуктивність\n\n```TypeScript\n@Pipe({ name: 'myPipe', pure: true })\n```\n\n**Impure pipe**\n\n- Викликається на кожен change detection\n\n- Використовувати обережно\n\n```TypeScript\n@Pipe({ name: 'myPipe', pure: false })\n```\n\n4. Pipe з параметрами\n\n```TypeScript\n@Pipe({ name: 'truncate', standalone: true })\nexport class TruncatePipe implements PipeTransform {\n  transform(value: string, limit = 10): string {\n    return value.length \u003e limit ? value.slice(0, limit) + '…' : value;\n  }\n}\n```\n\n```HTML\n\u003cp\u003e{{ text | truncate:20 }}\u003c/p\u003e\n```\n\n5. Best practices (Angular 20+)\n\n- Використовуйте standalone pipes\n\n- Тримайте pipes pure\n\n- Без side-effects\n\n- Не використовуйте pipes для складної бізнес-логіки\n\n- Для реактивних сценаріїв - signals або computed values\n\n**Коротко**\n\nPipe в Angular створюється через @Pipe, реалізує PipeTransform і\nвикористовується для декларативної трансформації даних у шаблоні.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e56. Опишіть чисті та нечисті канали.\u003c/summary\u003e\n\n#### Angular\n\nЧисті (Pure) та нечисті (Impure) канали в Angular\n\n#### Чисті канали (Pure Pipes)\n\n#### Характеристики\n\n- Викликаються **лише тоді**, коли змінюється **посилання на input**\n- Значення кешується Angular\n- Висока продуктивність\n- Повністю детерміновані (без side-effects)\n\n```TypeScript\n@Pipe({\n  name: 'uppercase',\n  standalone: true,\n  pure: true, // default\n})\nexport class UppercasePipe {}\n```\n\n#### Приклад використання\n\n```HTML\n\u003cp\u003e{{ name | uppercase }}\u003c/p\u003e\n```\n\n#### Коли використовувати\n\n- Форматування рядків\n\n- Обчислення на основі immutable-даних\n\n- 99% кейсів\n\n#### Нечисті канали (Impure Pipes)\n\n#### Характеристики\n\n- Викликаються на кожен цикл change detection\n- Не кешуються\n- Значно гірша продуктивність\n- Можуть мати side-effects (небажано)\n\n```TypeScript\nКопіювати код\n@Pipe({\n  name: 'timeAgo',\n  standalone: true,\n  pure: false,\n})\nexport class TimeAgoPipe {}\n```\n\n#### Приклад використання\n\n```HTML\n\u003cp\u003e{{ timestamp | timeAgo }}\u003c/p\u003e\n```\n\n#### Angular 20+ рекомендації\n\n- Завжди починайте з pure pipe\n\n- Уникайте impure pipes\n\n- Для реактивних сценаріїв:\n\n  - Signals (`computed`)\n\n  - RxJS + `async`\n\n- Impure pipe - останній варіант\n\n**Коротко**\n\nPure pipes - швидкі та безпечні, Impure pipes - повільні й використовуються лише\nу виняткових випадках.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e57. Що таке асинхронний канал і як він використовується?\u003c/summary\u003e\n\n#### Angular\n\nАсинхронний канал (`AsyncPipe`) в Angular\n\n#### Що таке `async` pipe\n\n`async` - це **вбудований Angular pipe**, який:\n\n- підписується на `Observable` або `Promise`\n- автоматично оновлює шаблон при нових значеннях\n- **сам відписуєт","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevloversteam%2Fangular-interview-questions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevloversteam%2Fangular-interview-questions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevloversteam%2Fangular-interview-questions/lists"}