{"id":13660145,"url":"https://github.com/Angular-RU/angular-ru-interview-questions","last_synced_at":"2025-04-24T19:30:36.387Z","repository":{"id":27322533,"uuid":"110573580","full_name":"Angular-RU/angular-ru-interview-questions","owner":"Angular-RU","description":"Вопросы на собеседовании по Angular","archived":false,"fork":false,"pushed_at":"2023-07-11T05:30:35.000Z","size":683,"stargazers_count":377,"open_issues_count":3,"forks_count":120,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-04-05T04:13:27.835Z","etag":null,"topics":["angular","angular-cli","angular-interview-questions","dom","enterprise","frontend","interview","interview-questions","javascript","mvvm","ng-container","ng-template","rxjs","typescript"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Angular-RU.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-11-13T16:36:26.000Z","updated_at":"2025-03-31T15:22:36.000Z","dependencies_parsed_at":"2024-01-15T20:51:46.011Z","dependency_job_id":"9ca0fcf6-fcd3-493a-bb07-3d5f073703ba","html_url":"https://github.com/Angular-RU/angular-ru-interview-questions","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Angular-RU%2Fangular-ru-interview-questions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Angular-RU%2Fangular-ru-interview-questions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Angular-RU%2Fangular-ru-interview-questions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Angular-RU%2Fangular-ru-interview-questions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Angular-RU","download_url":"https://codeload.github.com/Angular-RU/angular-ru-interview-questions/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250693428,"owners_count":21472259,"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","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":["angular","angular-cli","angular-interview-questions","dom","enterprise","frontend","interview","interview-questions","javascript","mvvm","ng-container","ng-template","rxjs","typescript"],"created_at":"2024-08-02T05:01:17.334Z","updated_at":"2025-04-24T19:30:36.070Z","avatar_url":"https://github.com/Angular-RU.png","language":null,"readme":"## Вопросы на собеседовании по Angular [![Angular-RU](https://img.shields.io/badge/Telegram_chat:-Angular_RU-216bc1.svg?style=flat)](https://t.me/angular_ru)\n\nВопросы подготовлены непосредственно для того, чтобы определить уровень разработчика, насколько глубоко, поверхностно или сносно он знает Angular. Вопросы для собеседования на знание JavaScript или Web-стека хорошо освещены в других местах, поэтому ниже будет добавлен список ресурсов по этой теме:\n\n**Fundamentals**:\n\n- [Coding Interview University](https://github.com/jwasham/coding-interview-university)\n- [Awesome Interviews](https://github.com/alex/what-happens-when)\n- [Angular Interview Questions](https://github.com/sudheerj/angular-interview-questions)\n\n**Frontend**:\n\n- [Front-end Job Interview Questions](https://github.com/h5bp/Front-end-Developer-Interview-Questions)\n- [The Best Frontend JavaScript Interview Questions](\u003chttps://performancejs.com/post/hde6d32/The-Best-Frontend-JavaScript-Interview-Questions-(Written-by-a-Frontend-Engineer)\u003e)\n- [Frontend Guidelines Questionnaire](https://github.com/bradfrost/frontend-guidelines-questionnaire)\n- [Подготовка к интервью на Front-end разработчика](https://proglib.io/p/frontend-interview/)\n\n**Angular**:\n\n- [Angular Interview Questions by Google Developer Expert](https://github.com/Yonet/Angular-Interview-Questions)\n\n##### Базовые вопросы для Junior/Middle\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем отличие фреймворка от библиотеки (приведите примеры и отличия)?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКакие популярные CSS, JS библиотеки вы знаете?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЗнаете ли вы как браузер обрабатывает index.html (расскажите про Critical Rendering Path)?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКакие типы данных есть в JavaScript?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак устроена память в JavaScript (memory heap, memory stack)?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое this и расскажите про область видимости?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем отличие var от const, let?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eОбъясните, как работает наследование прототипов, что такое цепочка прототипов, и когда появилось ключевое слова class в JS?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое структура данных и какие виды вы знаете (Стек, etc)?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Promise и для чего используется в JS?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое call-stack, task-queue (приведите примеры работы)?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое макро и микро задачи в JS?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eНазовите основные принципы ООП?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое класс и интерфейс?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое конструктор класса?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eРасскажите про стек TCP/IP, а также более подробно про, что такое HTTP и какую роль он играет при разработке приложений?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое REST API, как происходит взаимодействие (расскажите про основные коды ошибок, заголовки пакетов и способы их отправки)?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Основны TypeScript\n\n\u003cdetails\u003e\n\u003csummary\u003eЗачем нам нужны определения типов, где есть JavaScript c динамической типизацией?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое пользовательский тип данных\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Union Type (тип объединения) и для чего используется?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eПоддерживает ли TypeScript перегрузку методов?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВозможна ли перегрузка конструктора в TypeScript?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eПоддерживает ли TypeScript перегрузку методов (конструкторов)?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое декоратор и какие виды декораторов вы знаете?\u003c/summary\u003e\n\n\u003cbr\u003e\n\nДекоратор — способ добавления метаданных к объявлению класса. Это специальный вид объявления, который может быть присоединен к объявлению класса, методу, методу доступа, свойству или параметру. \u003cbr\u003e\n\u003cbr\u003eДекораторы используют форму @expression, где expression - функция, которая будет вызываться во время выполнения с информацией о декорированном объявлении.\u003cbr\u003e\n\u003cbr\u003eИ, чтобы написать собственный декоратор, нам нужно сделать его factory и определить тип:\n\n  \u003cul\u003e\n    \u003cli\u003eClassDecorator\u003c/li\u003e\n    \u003cli\u003ePropertyDecorator\u003c/li\u003e\n    \u003cli\u003eMethodDecorator\u003c/li\u003e\n    \u003cli\u003eParameterDecorator\u003c/li\u003e\n  \u003c/ul\u003e\n    \n  \u003cb\u003eДекоратор класса\u003c/b\u003e\n  \u003cdiv\u003e\n\nВызывается перед объявлением класса, применяется к конструктору класса и может использоваться для наблюдения, изменения или замены определения класса. Expression декоратора класса будет вызываться как функция во время выполнения, при этом конструктор декорированного класса является единственным аргументом. Если класс декоратора возвращает значение, он заменит объявление класса вернувшимся значением. \u003cbr\u003e\n\n```ts\nexport function logClass(target: Function) {\n  // Сохранение ссылки на оригинальный конструктор\n  const original = target;\n\n  // Функция генерирует экземпляры класса\n  function construct(constructor, args) {\n    const c: any = function () {\n      return constructor.apply(this, args);\n    };\n    c.prototype = constructor.prototype;\n    return new c();\n  }\n\n  // Определение поведения нового конструктора\n  const f: any = function (...args) {\n    console.log(`New: ${original[\"name\"]} is created`);\n    //New: Employee создан\n    return construct(original, args);\n  };\n\n  // Копирование прототипа, чтобы оператор intanceof работал\n  f.prototype = original.prototype;\n\n  // Возвращает новый конструктор, переписывающий оригинальный\n  return f;\n}\n\n@logClass\nclass Employee {}\n\nlet emp = new Employee();\nconsole.log(\"emp instanceof Employee\");\n//emp instanceof Employee\nconsole.log(emp instanceof Employee);\n//true\n```\n\n  \u003c/div\u003e\n  \n  \u003cbr\u003e\u003cb\u003eДекоратор свойства\u003c/b\u003e\n  \n  \u003cdiv\u003e\n  \n  Объявляется непосредственно перед объявлением метода. Будет вызываться как функция во время выполнения со следующими двумя аргументами:\n \n  \u003cul\u003e\n    \u003cli\u003etarget - прототип текущего объекта, т.е. если Employee является объектом, Employee.prototype\u003c/li\u003e\n    \u003cli\u003epropertyKey - название свойства\u003c/li\u003e\n  \u003c/ul\u003e\n\n```ts\nfunction logParameter(target: Object, propertyName: string) {\n  // Значение свойства\n  let _val = this[propertyName];\n\n  // Геттер свойства\n  const getter = () =\u003e {\n    console.log(`Get: ${propertyName} =\u003e ${_val}`);\n    return _val;\n  };\n\n  // Сеттер свойства\n  const setter = (newVal) =\u003e {\n    console.log(`Set: ${propertyName} =\u003e ${newVal}`);\n    _val = newVal;\n  };\n\n  // Удаление свойства\n  if (delete this[propertyName]) {\n    // Создает новое свойство с геттером и сеттером\n    Object.defineProperty(target, propertyName, {\n      get: getter,\n      set: setter,\n      enumerable: true,\n      configurable: true,\n    });\n  }\n}\n\nclass Employee {\n  @logParameter\n  name: string;\n}\n\nconst emp = new Employee();\nemp.name = \"Mohan Ram\";\nconsole.log(emp.name);\n\n// Set: name =\u003e Mohan Ram\n// Get: name =\u003e Mohan Ram\n// Mohan Ram\n```\n\n  \u003c/div\u003e\n  \n  \u003cbr\u003e\u003cb\u003eДекоратор метода\u003c/b\u003e\n \n  \u003cdiv\u003e\n  \n  Объявляется непосредственно перед объявлением метода. Будет вызываться как функция во время выполнения со следующими двумя аргументами:\n \n  \u003cul\u003e\n    \u003cli\u003etarget - прототип текущего объекта, т.е. если Employee является объектом, Employee.prototype\u003c/li\u003e\n    \u003cli\u003epropertyName - название свойства\u003c/li\u003e\n    \u003cli\u003edescriptor - дескриптор свойства метода т.е. - Object.getOwnPropertyDescriptor (Employee.prototype, propertyName)\u003c/li\u003e\n  \u003c/ul\u003e\n \n   ```ts\n    export function logMethod(\n        target: Object,\n        propertyName: string,\n        propertyDescriptor: PropertyDescriptor): PropertyDescriptor {\n        const method = propertyDescriptor.value;\n    \n        propertyDescriptor.value = function (...args: any[]) {\n    \n            // Конвертация списка аргументов greet в строку\n            const params = args.map(a =\u003e JSON.stringify(a)).join();\n    \n            // Вызов greet() и получение вернувшегося значения\n            const result = method.apply(this, args);\n    \n            // Конвертация результата в строку\n            const r = JSON.stringify(result);\n    \n            // Отображение в консоли деталей вызова\n            console.log(`Call: ${propertyName}(${params}) =\u003e ${r}`);\n    \n            // Возвращение результата вызова\n            return result;\n        }\n        return propertyDescriptor;\n    }\n    \n    class Employee {\n    \n        constructor(\n            private firstName: string,\n            private lastName: string\n        ) {\n        }\n    \n        @logMethod\n        greet(message: string): string {\n            return `${this.firstName} ${this.lastName} says: ${message}`;\n        }\n    \n    }\n    \n    const emp = new Employee('Mohan Ram', 'Ratnakumar');\n    emp.greet('hello');\n    //Call: greet(\"hello\") =\u003e \"Mohan Ram Ratnakumar says: hello\"\n   ```\n   \u003c/div\u003e\n   \n   \u003cbr\u003e\u003cb\u003eДекоратор параметра\u003c/b\u003e\n\n\u003cdiv\u003e\n\nОбъявляется непосредственно перед объявлением метода. Будет вызываться как функция во время выполнения со следующими двумя аргументами:\n\n  \u003cul\u003e\n    \u003cli\u003etarget - прототип текущего объекта, т.е. если Employee является объектом, Employee.prototype\u003c/li\u003e\n    \u003cli\u003epropertyKey - название свойства\u003c/li\u003e\n    \u003cli\u003eindex - индекс параметра в массиве аргументов\u003c/li\u003e\n  \u003c/ul\u003e\n  \n\u003c/div\u003e\n\n```ts\nfunction logParameter(target: Object, propertyName: string, index: number) {\n  // Генерация метаданных для соответствующего метода\n  // для сохранения позиции декорированных параметров\n  const metadataKey = `log_${propertyName}_parameters`;\n\n  if (Array.isArray(target[metadataKey])) {\n    target[metadataKey].push(index);\n  } else {\n    target[metadataKey] = [index];\n  }\n}\n\nclass Employee {\n  greet(@logParameter message: string): void {\n    console.log(`hello ${message}`);\n  }\n}\nconst emp = new Employee();\nemp.greet(\"world\");\n```\n\n\u003c/details\u003e\n\n##### Основные концепции\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Angular?\u003c/summary\u003e\n\u003cdiv\u003e\u003cbr\u003e\n\u003cimg src=\"https://d2eip9sf3oo6c2.cloudfront.net/series/square_covers/000/000/033/thumb/egghead-angular-material-course-sq.png\" align=\"left\" alt=\"\"\u003e\u003cp\u003e\u003cb\u003eAngular\u003c/b\u003e\u0026nbsp;\u0026mdash; это платформа для разработки мобильных и\u0026nbsp;десктопных веб-приложений. Наши приложения теперь представляют из\u0026nbsp;себя \u0026laquo;толстый клиент\u0026raquo;, где управление отображением и\u0026nbsp;часть логики перенесены на\u0026nbsp;сторону браузера. Так сервер уделяет больше времени доставке данных, плюс пропадает необходимость в\u0026nbsp;постоянной перерисовке. С\u0026nbsp;Angular мы\u0026nbsp;описываем структуру приложения декларативно, а\u0026nbsp;с\u0026nbsp;TypeScript начинаем допускать меньше ошибок, благодаря статической типизации. В\u0026nbsp;Angular присутствует огромное количество возможностей из\u0026nbsp;коробки. Это может быть одновременно и\u0026nbsp;хорошо и\u0026nbsp;плохо, в\u0026nbsp;зависимости от\u0026nbsp;того, что вам необходимо.\u003c/p\u003e\u003chr\u003e\n  \n\u003cb\u003eКакие плюсы можно выделить\u003c/b\u003e:\n\u003cul\u003e\n  \u003cli\u003eПоддержка Google, Microsoft\u003c/li\u003e\n  \u003cli\u003eИнструменты разработчика (CLI)\u003c/li\u003e\n  \u003cli\u003eTypescript из коробки\u003c/li\u003e\n  \u003cli\u003eРеактивное программирование с RxJS\u003c/li\u003e\n  \u003cli\u003eЕдинственный фреймворк с Dependency Injection из коробки\u003c/li\u003e\n  \u003cli\u003eШаблоны, основанные на расширении HTML\u003c/li\u003e\n  \u003cli\u003eКроссбраузерный Shadow DOM из коробки (либо его эмуляция) \u003c/li\u003e\n  \u003cli\u003eКроссбраузерная поддержка HTTP, WebSockets, Service Workers\u003c/li\u003e\n  \u003cli\u003eНе нужно ничего дополнительно настраивать. Больше никаких оберток. jQuery плагины и D3 можно использовать на прямую\u003c/li\u003e\n  \u003cli\u003eБолее современный фреймворк, чем AngularJS (на уровне React, Vue)\u003c/li\u003e\n  \u003cli\u003eБольшое комьюнити\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003cb\u003eМинусы\u003c/b\u003e:\n\n\u003cul\u003e\n  \u003cli\u003eВыше порог вхождения из-за Observable (RxJS) и Dependency Injection\u003c/li\u003e\n  \u003cli\u003eЧтобы все работало хорошо и быстро нужно тратить время на дополнительные оптимизации \n    (он не супер быстрый, по умолчанию, но быстрее AngularJS во много раз)\u003c/li\u003e\n  \u003cli\u003eЕсли вы планируете разрабатывать большое enterprise-приложение, то в этом случае, у вас нет архитектуры из коробки - нужно добавлять Mobx, Redux, MVVM, CQRS/CQS или другой state-менеджер, чтобы потом не сломать себе мозг\u003c/li\u003e\n  \u003cli\u003eAngular-Universal имеет много подводных камней\u003c/li\u003e\n  \u003cli\u003eДинамическое создание компонентов оказывается нетривиальной задачей\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем разница между AngularJS и Angular?\u003c/summary\u003e\n\u003cdiv\u003e\n  \n\u003cbr\u003e\u003cb\u003eAngularJS\u003c/b\u003e является фреймворком, который может помочь вам в разработке Single Page Application. Он появился в 2009 году и с годами выяснилось, что имел много проблем. \u003cb\u003eAngular\u003c/b\u003e (Angular 2+) же в свою очередь направлен на тоже самое, но дает больше преимуществ по сравнению с AngularJS 1.x, включая лучшую производительность, ленивую загрузку, более простой API, более легкую отладку.\n\n\u003cb\u003eЧто появилось в Angular\u003c/b\u003e: \u003cbr\u003e\n\n\u003cul\u003e\n  \u003cli\u003eAngular ориентирован на мобильные платформы и имеет лучшую производительность\u003c/li\u003e  \n  \u003cli\u003eAngular имеет встроенные сервисы для поддержки интернационализации\u003c/li\u003e\n  \u003cli\u003eAngularJS проще настроить, чем Angular\u003c/li\u003e\n  \u003cli\u003eAngularJS использует контроллеры и $scope\u003c/li\u003e\n  \u003cli\u003eAngular имеет много способов определения локальных переменных\u003c/li\u003e\n  \u003cli\u003eВ Angular новый синтаксис структурных директив (camelCase)\u003c/li\u003e\n  \u003cli\u003eAngular работает напрямую с свойствами и событиями DOM элементов\u003c/li\u003e\n  \u003cli\u003eОдностороннее связывание данных через [property]\u003c/li\u003e\n  \u003cli\u003eДвустороннее связывание данных через [(property)]\u003c/li\u003e\n  \u003cli\u003eНовый механизм DI, роутинга, запуска приложения\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003cb\u003eОсновные преимущества Angular\u003c/b\u003e: \u003cbr\u003e\n\n\u003cul\u003e\n  \u003cli\u003eОбратная совместимость Angular 2, 4, 5, ..\u003c/li\u003e\n  \u003cli\u003eTypeScript с улучшенной проверкой типов\u003c/li\u003e\n  \u003cli\u003eВстроенный компилятор с режимами JIT и AOT (+сокращение кода)\u003c/li\u003e\n  \u003cli\u003eВстроенные анимации\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКакой должна быть структура каталогов компонентов любого Angular приложения и почему?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое MVVM и в чем разница перед MVC?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003e \u003cb\u003eMVVM\u003c/b\u003e - шаблон проектирования архитектуры приложения. Состоит из 3 ключевых блоков: Model, View, ViewModel.\n  \u003cbr\u003eОтличие от MVС заключаются в: \u003cbr\u003e \u003cbr\u003e\n  \n  \u003cli\u003eView реагирует на действия пользователя и передает их во View Model через Data Binding.\u003c/li\u003e\n  \u003cli\u003eView Model, в отличие от контроллера в MVC, имеет особый механизм, автоматизирующий связь между View и связанными свойствами в ViewModel.\u003c/li\u003e\n  \n  \u003cbr\u003eПривязка данных между View и ViewModel может быть односторонней или двусторонней (one-way, two-way data-binding).\n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Angular Template синтаксис\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое интерполяция в Angular?\u003c/summary\u003e\n\u003cdiv\u003e\u003cbr\u003e\n  \nРазметка интерполяции с внедренными выражениями используется в Angular для присвоения данных текстовым нодам и значения аттрибутов. Например:\n  \n  ```html\n    \u003ca href=\"img/{{username}}.jpg\"\u003eHello {{username}}!\u003c/a\u003e\n  ```\n  \n\u003cbr\u003e\n\u003c/div\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКакие способы использования шаблонов в Angular вы знаете?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем разница между структурной и атрибутной директивой, назовите встроенные директивы?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003e\u003cli\u003eСтруктурные директивы влияют на DOM и могут добавлять/удалять элементы  \u003cbr\u003e (ng-template, NgIf, NgFor, NgSwitch, etc) \u003c/li\u003e\n  \u003cli\u003eАтрибутные директивы меняют внешний вид или поведение элементов, компонентов или других директив  \u003cbr\u003e (NgStyle, NgClass, etc).\u003c/li\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eДля чего нужны директивы ng-template, ng-container, ng-content?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003ch4\u003e1. ng-template\u003c/h4\u003e\n  \n  `\u003ctemplate\u003e` — это механизм для отложенного рендера клиентского контента, который не отображается во время загрузки, но может быть инициализирован при помощи JavaScript. \u003cbr\u003e\u003cbr\u003e\n  Template можно представить себе как фрагмент контента, сохранённый для последующего использования в документе. Хотя парсер и обрабатывает содержимое элемента `template` во время загрузки страницы, он делает это только чтобы убедиться в валидности содержимого; само содержимое при этом не отображается. \u003cbr\u003e\u003cbr\u003e\n  \n  `\u003cng-template\u003e` - является имплементацией стандартного элемента template, данный элемент появился с четвертой версии Angular, это было сделано с точки зрения совместимости со встраиваемыми на страницу template элементами, которые могли попасть в шаблон ваших компонентов по тем или иным причинам. \u003cbr\u003e\u003cbr\u003e\n\nПример:\n\n```html\n\u003cdiv class=\"lessons-list\" *ngIf=\"lessons else loading\"\u003e...\u003c/div\u003e\n\n\u003cng-template #loading\u003e\n  \u003cdiv\u003eLoading...\u003c/div\u003e\n\u003c/ng-template\u003e\n```\n\n  \u003ch4\u003e2. ng-container\u003c/h4\u003e\n  \n  `\u003cng-container\u003e` - это логический контейнер, который может использоваться для группировки узлов, но не отображается в дереве DOM как узел (node).\n\nНа самом деле структурные директивы (*ngIf, *ngFor, …) являются синтаксическим сахаром для наших шаблонов. В реальности, данные шаблоны трансформируются в такие конструкции:\n\n```html\n\u003cng-template [ngIf]=\"lessons\" [ngIfElse]=\"loading\"\u003e\n   \u003cdiv class=\"lessons-list\"\u003e\n     ...\n   \u003c/div\u003e\n\u003c/div\u003e\n\n\u003cng-template #loading\u003e\n    \u003cdiv\u003eLoading...\u003c/div\u003e\n\u003c/ng-template\u003e\n```\n\nНо что делать, если я хочу применить несколько структурных директив?\n(спойлер: к сожалению, так нельзя сделать)\n\n```html\n\u003cdiv class=\"lesson\" *ngIf=\"lessons\" *ngFor=\"let lesson of lessons\"\u003e\n  \u003cdiv class=\"lesson-detail\"\u003e{{lesson | json}}\u003c/div\u003e\n\u003c/div\u003e\n```\n\n```\nUncaught Error: Template parse errors:\nCan't have multiple template bindings on one element. Use only one attribute\nnamed 'template' or prefixed with *\n```\n\nНо можно сделать так:\n\n```html\n\u003cdiv *ngIf=\"lessons\"\u003e\n  \u003cdiv class=\"lesson\" *ngFor=\"let lesson of lessons\"\u003e\n    \u003cdiv class=\"lesson-detail\"\u003e{{lesson | json}}\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n```\n\nОднако, чтобы избежать необходимости создавать дополнительный div, мы можем вместо этого использовать директиву ng-container:\n\n```html\n\u003cng-container *ngIf=\"lessons\"\u003e\n  \u003cdiv class=\"lesson\" *ngFor=\"let lesson of lessons\"\u003e\n    \u003cdiv class=\"lesson-detail\"\u003e{{lesson | json}}\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/ng-container\u003e\n```\n\nКак мы видим, директива ng-container предоставляет нам элемент, в котором мы можем использовать структурную директиву, без необходимости создавать дополнительный элемент.\n\nЕще пара примечательных примеров, если все же вы хотите использовать ng-template вместо ng-container, по определенным правилам вы не сможете использовать полную конструкцию структурных директив.\n\nВы можете писать либо так:\n\n```html\n\u003cdiv class=\"mainWrap\"\u003e\n  \u003cng-container *ngIf=\"true\"\u003e\n    \u003ch2\u003eTitle\u003c/h2\u003e\n    \u003cdiv\u003eContent\u003c/div\u003e\n  \u003c/ng-container\u003e\n\u003c/div\u003e\n```\n\nЛибо так:\n\n```html\n\u003cdiv class=\"mainWrap\"\u003e\n  \u003cng-template [ngIf]=\"true\"\u003e\n    \u003ch2\u003eTitle\u003c/h2\u003e\n    \u003cdiv\u003eContent\u003c/div\u003e\n  \u003c/ng-template\u003e\n\u003c/div\u003e\n```\n\nНа выходе, при рендеринге будет одно и тоже:\n\n```html\n\u003cdiv class=\"mainWrap\"\u003e\n  \u003ch2\u003eTitle\u003c/h2\u003e\n  \u003cdiv\u003eContent\u003c/div\u003e\n\u003c/div\u003e\n```\n\n \u003ch4\u003e3. ng-content\u003c/h4\u003e\n \n`\u003cng-content\u003e` - позволяет внедрять родительским компонентам html-код в дочерние компоненты.\n \nЗдесь на самом деле, немного сложнее уже чем с ng-template, ng-container. Так как ng-content решает задачу проецирования контента в ваши веб-компоненты. Веб-компоненты состоят из нескольких отдельных технологий. Вы можете думать о Веб-компонентах как о переиспользуемых виджетах пользовательского интерфейса, которые создаются с помощью открытых веб-технологий. Они являются частью браузера и поэтому не нуждаются во внешних библиотеках, таких как jQuery или Dojo. Существующий Веб-компонент может быть использован без написания кода, просто путем импорта выражения на HTML-страницу. Веб-компоненты используют новые или разрабатываемые стандартные возможности браузера.\n\nДавайте представим ситуацию от обратного, нам нужно параметризовать наш компонент. Мы хотим сделать так, чтобы на вход в компонент мы могли передать какие-либо статичные данные. Это можно сделать несколькими способами.\n\ncomment.component.ts:\n\n```ts\n@Component({\n  selector: \"comment\",\n  template: `\n    \u003ch1\u003eКомментарий:\u003c/h1\u003e\n    \u003cp\u003e{{ data }}\u003c/p\u003e\n  `,\n})\nexport class CommentComponent {\n  @Input() data: string = null;\n}\n```\n\napp.component.html\n\n```html\n\u003cdiv *ngFor=\"let message of comments\"\u003e\n  \u003ccomment [data]=\"message\"\u003e\u003c/comment\u003e\n\u003c/div\u003e\n```\n\nНо можно поступить и другим путем. \u003cbr\u003e\ncomment.component.ts:\n\n```ts\n@Component({\n  selector: \"comment\",\n  template: `\n    \u003ch1\u003eКомментарий:\u003c/h1\u003e\n    \u003cng-content\u003e\u003c/ng-content\u003e\n  `,\n})\nexport class CommentComponent {}\n```\n\napp.component.html\n\n```html\n\u003cdiv *ngFor=\"let message of comments\"\u003e\n  \u003ccomment\u003e\n    \u003cp\u003e{{message}}\u003c/p\u003e\n  \u003c/comment\u003e\n\u003c/div\u003e\n```\n\nКонечно, эти примеры плохо демонстрируют подводные камни, свои плюсы и минусы. Но второй способ демонстрирует подход при работе, когда мы оперируем независимыми абстракциями и можем проецировать контент внутрь наших компонентов (подход веб-компонентов).\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Angular development environments\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое директива и как создать собственную?\u003c/summary\u003e\n\u003cdiv\u003e\n\n\u003cbr\u003e\n\nДирективы бывают трех видов: компонент, структурные и атрибутные (см. выше).\n\n\u003ch4\u003eСоздание атрибутных директив:\u003c/h4\u003e\n  \n```ts\n@Directive({ \n   selector: '[appHighlight]' \n})\nexport class HighlightDirective {  }\n```\n\n\u003cbr\u003e\n\nДекоратор определяет селектор атрибута [appHighlight], [] - указывают что это селектор атрибута. Angular найдет каждый элемент в шаблоне с этим атрибутом и применит к ним логику директивы.\n\n```ts\n@Directive({\n  selector: \"[appHighlight]\",\n})\nexport class HighlightDirective {\n  constructor(el: ElementRef) {\n    el.nativeElement.style.backgroundColor = \"yellow\";\n  }\n}\n```\n\n\u003cbr\u003eНеобходимо указать в конструкторе ElementRef, чтобы через его свойство nativeElement иметь прямой доступ к DOM элементу, который должен быть изменен.\n\u003cbr\u003eТеперь, используя @HostListener, можно добавить обработчики событий, взаимодействующие с декоратором.\n\n```ts\n@Component()\nclass EtcComponent {\n  @HostListener(\"mouseenter\")\n  public onMouseEnter(): void {\n    this.highlight(\"yellow\");\n  }\n\n  @HostListener(\"mouseleave\")\n  public onMouseLeave(): void {\n    this.highlight(null);\n  }\n\n  private highlight(color: string): void {\n    this.el.nativeElement.style.backgroundColor = color;\n  }\n}\n```\n\n\u003ch4\u003eСтруктурные директивы создаются так:\u003c/h4\u003e\n\nНапишем UnlessDirective, которая будет противоположна NgIf.\n\u003cbr\u003eНеобходимо использовать @Directive, и импортировать Input, TemplateRef, и ViewContainerRef. Они вам понадобятся при воздании любой структурной директивы.\n\n```ts\nimport { Directive, Input, TemplateRef, ViewContainerRef } from \"@angular/core\";\n\n@Directive({ selector: \"[appUnless]\" })\nexport class UnlessDirective {}\n```\n\nВ конструкторе мы получаем доступ к view container и содержимое \u003cng-template\u003e.\n\n```\n  constructor(\n    private templateRef: TemplateRef\u003cany\u003e,\n    private viewContainer: ViewContainerRef) { }\n```\n\nНаша директива предполагает работу с true/false. Для этого нужно свойство appUnless, добавленное через @Input.\n\n```ts\n@Directive({ selector: \"[appUnless]\" })\nexport class UnlessDirective {\n  @Input() public set appUnless(condition: boolean) {\n    if (!condition \u0026\u0026 !this.hasView) {\n      this.viewContainer.createEmbeddedView(this.templateRef);\n      this.hasView = true;\n    } else if (condition \u0026\u0026 this.hasView) {\n      this.viewContainer.clear();\n      this.hasView = false;\n    }\n  }\n}\n```\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое директива, компонент, модуль, сервис, пайп в Angular и для чего они нужны?\u003c/summary\u003e\n\n\u003cdiv\u003e\n    \u003cbr\u003e\n    \u003cul\u003e\n      \u003cli\u003eДиректива - см. выше.\u003c/li\u003e\n      \u003cli\u003eКомпонент контролирует участок экрана, т.н. view.\u003c/li\u003e\n      \u003cli\u003eСервис это класс с узкой, четко определенной целью. Это может быть значение, функция, запрос, etc. Главное в них то, что они повторно используются, отделяя чистую функциональность компонента. \u003c/li\u003e\n      \u003cli\u003eПайп преобразует отображение значений в шаблоне, к примеру отображение дат в разных локалях или изменяют в отображении регистр строк.\u003c/li\u003e\n    \u003c/ul\u003e\n\u003c/div\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eРасскажите об основных параметрах @NgModule, @Component, @Directive, @Injectable, @Pipe\u003c/summary\u003e\n\u003cdiv\u003e\n \u003cbr\u003e\n \n Декораторы динамически подключают дополнительное поведение к объекту. Они помечают класс и предоставляют конфигурационные метаданные.\n \u003ch4\u003e@NgModule может содержать следующие параметры:\u003c/h4\u003e\n \u003cli\u003eproviders - список инжектируемых объектов, которые добавляются в этот модуль\u003c/li\u003e\n \u003cli\u003edeclarations - компоненты, директивы и пайпы, принадлежащие этому модулю\u003c/li\u003e\n \u003cli\u003eimports - модули, которые экспортируются декларируемыми и доступны в шаблоне этого модуля\u003c/li\u003e\n \u003cli\u003eexports - компоненты, директивы и пайпы, которые объявлены декларируемыми, и могут быть им пользованы в шаблоне любого компонента, которые принадлежит NgModule импортирующему их.\u003c/li\u003e\n \u003cli\u003eentryComponent - компилируемые компоненты при определении NgModule, для динамической загрузки в view.\u003c/li\u003e\n \u003cli\u003ebootstrap - компоненты, которые загружаются при загрузке этого модуля, автоматически добавляются в entryComponent. \u003c/li\u003e\n \u003cli\u003eschemas - набор схем, объявляющих разрешенные элементы в MgModules\u003c/li\u003e\n \u003cli\u003eid - имя или путь, уникальный идентификатор этого NgModule в getModuleFactory. Если не заполнять - не будет там зарегистрирован.\u003c/li\u003e\n \u003cli\u003ejit - если true, то этот модуль будет пропущен компилятором AOT и всегда будет компилироваться JIT.\u003c/li\u003e\n \n \u003ch4\u003e@Component может содержать следующие параметры:\u003c/h4\u003e\n \u003cli\u003echangeDetection - стратегия обнаружения изменений, используемая для этого компонента\u003c/li\u003e\n \u003cli\u003eviewProviders - инжектируемые объекты, которые видны DOM children этого компонента. \u003c/li\u003e\n \u003cli\u003emoduleId - id модуля, к которому относится компонент.\u003c/li\u003e\n \u003cli\u003etemplateUrl - относительный путь или абсолютный URL к шаблону компонента.\u003c/li\u003e\n \u003cli\u003etemplate - инлайн шаблон для этого компонента.\u003c/li\u003e\n \u003cli\u003estyleUrls - один и более путь до файла, содержащего CSS, абсолютный или относительный.\u003c/li\u003e\n \u003cli\u003estyles - инлайн CSS, используемые в этом компоненте.\u003c/li\u003e\n \u003cli\u003eanimations - один и более вызовов анимации trigger(), содержащих state() и transition(). \u003c/li\u003e\n \u003cli\u003eencapsulation - правила инкапсуляции для шаблона и CSS.\u003c/li\u003e\n \u003cli\u003einterpolation - переопределение базовых знаков интерполяции.\u003c/li\u003e\n \u003cli\u003eentryComponents - компоненты, которые должны быть скомпилированы вместе с этим компонентом. Для каждого упомянутого здесь компонента создается ComponentFactory и сохраняется в ComponentFactoryResolver.\u003c/li\u003e\n \u003cli\u003epreserveWhitespaces - при значении true удаляются потенциально лишние пробелы из скомпилированного шаблона. \u003c/li\u003e\n \n \u003ch4\u003e@Directive может содержать следующие параметры:\u003c/h4\u003e\n  \u003cli\u003eselector - CSS-селектор, который идентифицирует эту директиву в шаблоне и запускает создание этой директивы.\u003c/li\u003e\n  \u003cli\u003einputs - свойство для определения значение @Input() параметра. Значение из inputs можно сразу использовать в шаблоне, без объявления переменной в классе. Пример объявления: inputs: ['name', 'id: id-from-parent']. Значение в inputs массиве может состоять из:\n    \u003cul\u003e\n      \u003cli\u003e directiveProperty - наименование свойства @Input, которое будет использоваться в дочернем компоненте для вывода в шаблоне и использования в самом классе.\n      \u003cli\u003e bindingProperty - наименование свойства, из которого будет производится чтение и запись в directiveProperty. Не обязательное. При отсутсвии параметра значение будет браться из directiveProperty\n    \u003c/ul\u003e\n    Пример использования:\n\n```ts\n@Component({\n  selector: \"child-component\",\n  template: `Name {{ name }} Id {{ id }}`,\n  inputs: [\"name\", \"id: parentId\"],\n})\nexport class ChildComponent {}\n\n@Component({\n  selector: \"parent-component\",\n  template: `\n    \u003cchild-component\n      [name]=\"parentName\"\n      [parentId]=\"parentIdValue\"\n    \u003e\u003c/child-component\u003e\n  `,\n})\nexport class Parent {\n  public parentIdValue = \"123\";\n  public parentName = \"Name\";\n}\n```\n\n  \u003c/li\u003e\n  \u003cli\u003eoutputs - свойство для определения @Output. В отличии от inputs, объявление свойства в классе обязательно. Пример:\n\n```ts\n@Component({\n  selector: \"child-dir\",\n  outputs: [\"bankNameChange\"],\n  template: `\u003cinput (input)=\"bankNameChange.emit($event.target.value)\" /\u003e`,\n})\nclass ChildDir {\n  bankNameChange: EventEmitter\u003cstring\u003e = new EventEmitter\u003cstring\u003e();\n}\n\n@Component({\n  selector: \"main\",\n  template: `\n    {{ bankName }}\n    \u003cchild-dir (bankNameChange)=\"onBankNameChange($event)\"\u003e\u003c/child-dir\u003e\n  `,\n})\nclass MainComponent {\n  bankName: string;\n\n  onBankNameChange(bankName: string) {\n    this.bankName = bankName;\n  }\n}\n```\n\n  \u003c/li\u003e\n  \u003cli\u003eproviders - настраивает инжектор этой директивы или компонента с помощью токена.\u003c/li\u003e\n  \u003cli\u003eexportAs - определяет имя, которое можно использовать в шаблоне для присвоения этой директивы переменной.\u003c/li\u003e\n  \u003cli\u003equeries - настраивает запросы, которые могут быть инжектированы в директиву.\u003c/li\u003e\n  \u003cli\u003ehost - составляет свойства класса со сбайнженными элементами для свойств, атрибутов и ивентов. \u003c/li\u003e\n  \u003cli\u003ejit - если true, то этот модуль будет пропущен компилятором AOT и всегда будет компилироваться JIT.\u003c/li\u003e\n  \n  \u003ch4\u003e@Injectable может содержать следующие параметры:\u003c/h4\u003e\n  \u003cli\u003eprovidedIn - определяет, где будет заинжектировано, либо, если объявлено \"root\" распространится на все приложение. \u003c/li\u003e\n  \n  \u003ch4\u003e@Pipe может содержать следующие параметры:\u003c/h4\u003e\n  \u003cli\u003ename - имя пайпа, которое будет использовано в шаблоне.\u003c/li\u003e\n  \u003cli\u003epure - если true, то пайп считается \"чистым\", и метод transform() вызовется только при изменении его входных агрументов. По умолчанию стоит true. \u003c/li\u003e\n \n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое динамические компоненты и как их можно использовать в Angular?\u003c/summary\u003e\n\u003cdiv\u003e\n\u003cbr\u003e\n\n  \u003cp\u003eДинамические компоненты - компоненты, которые добавляются на страницу во время выполнения приложения (runtime). Динамические компоненты можно использовать в тех случаях, когда компонент можно отобразить не сразу при загрузке страницы. Например: диалоговые окна, нотификации, контент в табах.\u003c/p\u003e\n  \u003cp\u003eДля того, чтобы использовать динамические компоненты, необходимо убедиться, что:\n    \u003col\u003e\n      \u003cli\u003e добавлен элемент (\"якорь\") - ng-container/ng-template - на нужной странице/в шаблоне, куда будет помещен динамический компонент. Именно в этот элемент будет загружаться динамический компонент.\u003c/li\u003e\n      \u003cli\u003e в классе компонента определено свойство для хранения ng-container/ng-template. Например:\n\n```ts\n@Component({\n  template: `\u003cdiv\u003e\n    \u003cng-container #dynamicContent\u003e\u003c/ng-container\u003e\n  \u003c/div\u003e `,\n})\nexport class AppComponent {\n  @ViewChild(\"dynamicContent\", { read: ViewContainerRef })\n  public dynamicContainer: ViewContainerRef;\n}\n```\n\n  \u003c/li\u003e\n  \u003cli\u003e при загрузке страницы ng-container/ng-template определен и загружен. Проверить загрузку и определение \"якоря\" можно в хуке ngAfterViewInit()\u003c/li\u003e\n  \u003c/ol\u003e\n\n  \u003cp\u003e\n    В динамический компонент можно внедрить зависимости. Зависимости могут понадобится для общения основного и динамического компонентов. Перед внедрением зависимости нужно создать injector. Создание injector похоже на определение параметра providers в @NgModule. Пример создания Injector:\n\n```ts\n// класс, который будет использоваться в constructor\nexport abstract class IDynamicComponentProps {\n  public abstract onClickDynamicComponent(): void;\n  public abstract items: Array\u003cstring\u003e;\n}\n\n// Использование зависимости в динамическом компоненте\n@Component({\n  template: `\n    \u003cspan *ngFor='let item of dynamicItems'\u003e{{item}}\u003c/span\u003e\n    \u003cbutton (click)='onClick()'\u003e\u003c/button\u003e\n  `\n})\nexport class DynamicComponent {\n  public dynamicItems: Array\u003cstring\u003e =\n    this.dynamicComponentProps.items;\n  constructor(\n    private dynamicComponentProps: IDynamicComponentProps,\n  ) {}\n\n  public onClick(): void {\n    this.dynamicComponentProps.onClickDynamicComponent();\n  }\n}\n\n// Создание инжектора в сервисе или родительском компоненте\n@Component({\n  ...\n})\nexport class ParentComponent {\n  public onClickHandler: EventEmitter\u003cnumber\u003e = new EventEmitter();\n  public parentItems: Array\u003cstring\u003e = ['str1', 'str2'];\n  constructor(\n    private injector: Injector,\n  ) {}\n\n  public createInjector() {\n    const injector: Injector = Injector.create(\n        [\n          {\n            provide: IDynamicComponentProps,\n            useValue:{\n              onClickDynamicComponent: () =\u003e { this.onClickHandler.emit(0) },\n              items: this.parentItems\n            }\n          }\n        ],\n        this.injector\n      );\n  }\n}\n```\n\n  \u003c/p\u003e\n  \u003ch4\u003eПоследовательность действий для отображения динамического компонента\u003c/h4\u003e\n  \u003col\u003e\n    \u003cli\u003e Добавить в шаблон \"якорь\" для компонента, объявить переменную для работы с этим элементом\u003c/li\u003e\n    \u003cli\u003e Очистить содержимое динамического компонента (при необходимости)\u003c/li\u003e\n    \u003cli\u003e Создать ComponentFactory с помощью resolveComponentFactory()\u003c/li\u003e\n    \u003cli\u003e Вызвать метод из созданного ComponentFactory для создания компонента на странице.\u003c/li\u003e\n  \u003c/ol\u003e\n  \u003cp\u003eПримечание: Для динамического компонента не обязательно создавать Injector. Обязательным параметром для метода createComponent является только ComponentFactory.\u003c/p\u003e\n  \u003cp\u003eНиже указана последовательность действий, реализованная кодом. В примере используется Основной компонент (MainComponent), динамический компонент (DynamicCompoent) и сервис для рендера (MainComponentService)\u003c/p\u003e\n\n```ts\n//основной компонент\n@Component({\n  selector: \"main-component\",\n  template: `\u003ch1\u003eDynamic Component Example\u003c/h1\u003e\n    \u003cng-container #dynamicComponent\u003e\u003c/ng-container\u003e `,\n})\nexport class MainComponent {\n  @ViewChild(\"dynamicComponent\", { read: ViewContainerRef })\n  public dynamicContainer: ViewContainerRef;\n\n  public parentItems: Array\u003cstring\u003e = [\"str1\", \"str2\"];\n  constructor(private mainComponentService: MainComponentService) {\n    this.mainComponentService.onClickHandler().subscribe((x) =\u003e console.log(x));\n    // console - 0 form dynamic component\n  }\n\n  public ngAfterViewInit(): void {\n    this.mainComponentService.render(this.dynamicContainer, this.parentItems);\n  }\n}\n\n// класс для DI\nexport abstract class IDynamicComponentProps {\n  public abstract onClickDynamicComponent(): void;\n  public abstract items: Array\u003cstring\u003e;\n}\n\n// сервис для рендера\n@Injectable()\nexport class MainComponentService {\n  public onClickHandler: EventEmitter\u003cnumber\u003e = new EventEmitter();\n  constructor(\n    private componentFactoryResolver: ComponentFactoryResolver,\n    private injector: Injector\n  ) {}\n\n  public render(container: ViewContainerRef, parentItems: Array\u003cstring\u003e): void {\n    if (!isUndefined(container)) {\n      container.clear();\n    }\n\n    const injector: Injector = Injector.create(\n      [\n        {\n          provide: IDynamicComponentProps,\n          useValue: {\n            onClickDynamicComponent: () =\u003e {\n              this.onClickHandler.emit(0);\n            },\n            items: parentItems,\n          },\n        },\n      ],\n      this.injector\n    );\n\n    const factory = this.componentFactoryResolver.resolveComponentFactory(\n      DynamicCompoent\n    );\n\n    container.createComponent(factory, 0, injector);\n  }\n}\n\n//динамический компонент\n@Component({\n  template: `\n    \u003cspan *ngFor=\"let item of dynamicItems\"\u003e{{ item }}\u003c/span\u003e\n    \u003cbutton (click)=\"onClick()\"\u003e\u003c/button\u003e\n  `,\n})\nexport class DynamicComponent {\n  public dynamicItems: Array\u003cstring\u003e = this.dynamicComponentProps.items;\n  constructor(private dynamicComponentProps: IDynamicComponentProps) {}\n\n  public onClick(): void {\n    this.dynamicComponentProps.onClickDynamicComponent();\n  }\n}\n```\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак применить анимацию к компонентам?\u003c/summary\u003e\n\u003cdiv\u003e\n\u003cbr\u003e\n\n  \u003cp\u003eАнимации в Angular построены на основе функциональности CSS. При работе с анимациями нужно иметь ввиду, что применять анимацию можно только к тем свойствам, которые можно анимировать.\u003c/p\u003e\n  \n  Перед началом создания анимаций нужно:\n    \u003cul\u003e\n      \u003cli\u003e Подключить модуль BrowserAnimationsModule в основной модуль приложения (root)\u003c/li\u003e\n      \u003cli\u003e Подключить функции для анимации в нужном компоненте: \n    \u003c/ul\u003e\n\n```js\nimport {\n  trigger,\n  state,\n  style,\n  animate,\n  transition,\n  // ...\n} from \"@angular/animations\";\n```\n\n\u003cli\u003eДобавить свойство animations в декоратор компонента @Component():\u003c/li\u003e\u003cbr\u003e\n\n```ts\n@Component({\n  selector: 'app-root',\n  templateUrl: 'app.component.html',\n  styleUrls: ['app.component.css'],\n  animations: [\n    // animation triggers go here\n  ]\n})\n```\n\n  \u003cp\u003e\n    Анимация состоит из:\n    \u003col\u003e\n      \u003cli\u003eтриггера - событие, по которому возникает анимация. Для инициализации триггера используется функция \u003cb\u003etrigger()\u003c/b\u003e. В параметрах функции нужно указать событие, которое будет указано в компоненте и к которому будет привязана анимация. Так же, указывается массив из функций \u003cb\u003estate()\u003c/b\u003e и \u003cb\u003etransition()\u003c/b\u003e \u003c/li\u003e\n      \u003cli\u003eсостояний в конце перехода - стили, которые будут применятся к элементу в конце анимации. Для объявления состояний используется функция \u003cb\u003estate()\u003c/b\u003e. В функции нужно указать название состояния, указать стили состояния с помощью функции \u003cb\u003estyle()\u003c/b\u003e. Если анимация отключена (\u003cb\u003e[@.disabled]='true'\u003c/b\u003e), то стили конечных состояний нужно прописать.\u003c/li\u003e\n      \u003cli\u003eпромежуточных состояний - стилей, которые применяются к элементу между окончательными состояниями. С помощью промежуточных состояний можно анимировать переходы. Для этого используется функция \u003cb\u003etransition()\u003c/b\u003e. В функции нужно прописать выражение, в котором указано направление между состояниями и функции для определения стилей между состояниями, анимации.\u003c/li\u003e\n    \u003c/ol\u003e\n\n  \u003cp\u003eДля объявления триггера, нужно прописать функцию \u003cb\u003etrigger()\u003c/b\u003e в метаданных компонента, в свойстве \u003cb\u003eanimations\u003c/b\u003e. Первым параметром нужно указать событие, которое будет привязано в шаблоне к элементу. Вторым параметром нужно указать состояние \u003cb\u003estate()\u003c/b\u003e и анимации в \u003cb\u003etransition()\u003c/b\u003e. Например:\n\n```ts\n@Component({\n  selector: \"example\",\n  animations: [\n    trigger(\"toggle\", [\n      state(\n        \"open\",\n        style({\n          height: \"200px\",\n          opacity: 1,\n          backgroundColor: \"yellow\",\n        })\n      ),\n      state(\n        \"closed\",\n        style({\n          height: \"100px\",\n          opacity: 0.5,\n          backgroundColor: \"green\",\n        })\n      ),\n      transition(\"open =\u003e closed\", [animate(\"1s\")]),\n      transition(\"closed =\u003e open\", [animate(\"0.5s\")]),\n      //...\n    ]),\n  ],\n  template: `\u003cdiv [@toggle]=\"isOpen ? 'open' : 'closed'\"\u003e\u003c/div\u003e`,\n})\nexport class ExampleComponent {}\n```\n\n  \u003c/p\u003e\n  \u003ch4\u003eДополнительные состояния переходов\u003c/h4\u003e\n  \u003cp\u003eПри работе с переходами можно указывать не только состояния, указанные в функции state(). Анимации в Angular поддерживают следующие состояния:\n    \u003cul\u003e\n      \u003cli\u003e\u003cb\u003e*\u003c/b\u003e - любое состояние. Полезно для определения переходов, которые применяются независимо от начального или конечного состояния HTML-элемента. Можно использовать конструкцию \u003cb\u003e* =\u003e *\u003c/b\u003e, для того, чтобы определить переходы тем состояниям, у которых не назначена анимация. Эту конструкцию можно добавить после того, как будут перечислены конкретные переходы состояний.\u003c/li\u003e\n      \u003cli\u003e\u003cb\u003evoid\u003c/b\u003e - состояние, когда элемент появляется в DOM или удаляется из него. Например, при ngIf. Void входит в состояние *. \u003c/li\u003e\n    \u003c/ul\u003e\n\n```ts\nanimations: [\n  trigger(\"openClose\", [\n    state(\n      \"open\",\n      style({\n        height: \"200px\",\n        opacity: 1,\n        backgroundColor: \"yellow\",\n      })\n    ),\n    state(\n      \"closed\",\n      style({\n        height: \"100px\",\n        opacity: 0.5,\n        backgroundColor: \"green\",\n      })\n    ),\n    transition(\"open =\u003e closed\", [animate(\"1s\")]),\n    transition(\"closed =\u003e open\", [animate(\"0.5s\")]),\n    transition(\"* =\u003e closed\", [animate(\"1s\")]),\n    transition(\"* =\u003e open\", [animate(\"0.5s\")]),\n    transition(\"* =\u003e open\", [animate(\"1s\", style({ opacity: \"*\" }))]),\n    transition(\"* =\u003e *\", [animate(\"1s\")]),\n  ]),\n];\n```\n\n\u003cp\u003e\n    Два вышеперечисленных состояния можно использовать вместе - \u003cb\u003evoid =\u003e *\u003c/b\u003e и \u003cb\u003e * =\u003e void\u003c/b\u003e. У этих конструкций есть алиасы - :enter (void =\u003e *) и :leave (* =\u003e void). Например:\n\u003c/p\u003e\n\n```ts\nconst animation = trigger(\"eventTrigger\", [\n  transition(\"void =\u003e *\", [\n    style({ opacity: 0 }),\n    animate(\"5s\", style({ opacity: 1 })),\n  ]),\n  // or\n  transition(\":enter\", [\n    style({ opacity: 0 }),\n    animate(\"5s\", style({ opacity: 1 })),\n  ]),\n\n  //-------------//\n\n  transition(\"* =\u003e void\", [animate(\"5s\", style({ opacity: 0 }))]),\n  //or\n  transition(\":leave\", [animate(\"5s\", style({ opacity: 0 }))]),\n]);\n```\n\n  \u003cp\u003eДля работы с переходами можно использовать числовые и булевы значения. При работе с числовыми значениями, можно использовать алиасы :increment и :decrement. С булевыми значениями можно просто прописать true/false. Например:\n\n```ts\n@Component({\n  selector: \"toggle\",\n  animations: [\n    trigger(\"isOpen\", [\n      state(\"true\", style({ height: \"*\" })),\n      state(\"false\", style({ height: \"0px\" })),\n      transition(\"true \u003c=\u003e false\", [animate(\"1s\")]),\n    ]),\n  ],\n  template: `\u003cdiv [@isOpen]=\"isOpen ? true : false\"\u003e\u003c/div\u003e`,\n})\nexport class ToggleComponent {\n  public isOpen: boolean = true;\n}\n\n@Component({\n  template: `\u003cul class=\"heroes\" [@filterAnimation]=\"heroTotal\"\u003e\u003c/ul\u003e`,\n  animations: [\n    trigger(\"filterAnimation\", [\n      transition(\":enter, * =\u003e 0, * =\u003e -1\", []),\n      transition(\":increment\", [\n        query(\n          \":enter\",\n          [\n            style({ opacity: 0, width: \"0px\" }),\n            stagger(50, [\n              animate(\"300ms ease-out\", style({ opacity: 1, width: \"*\" })),\n            ]),\n          ],\n          { optional: true }\n        ),\n      ]),\n      transition(\":decrement\", [\n        query(\":leave\", [\n          stagger(50, [\n            animate(\"300ms ease-out\", style({ opacity: 0, width: \"0px\" })),\n          ]),\n        ]),\n      ]),\n    ]),\n  ],\n})\nexport class HeroListPageComponent implements OnInit {\n  public heroTotal: number = -1;\n}\n```\n\n  \u003c/p\u003e\n  \n\u003cp\u003e\u003cb\u003eПримечание:\u003c/b\u003e хорошей практикой является перенос анимаций в отдельные файлы *.animation.ts. Эта практика уменьшит размер файла компонента, обеспечит декомпозицию, даст возможность переиспользования анимаций.\u003c/p\u003e\n  \n[Гайд ангуляра по переиспользованию анимаций](https://angular.io/guide/reusable-animations)\n\n\u003ch4\u003eОтключение анимации\u003c/h4\u003e\n\u003cp\u003eАнимацию можно принудительно отключить как в отдельном компоненте, так и во всем приложении.\u003c/p\u003e\n\u003cp\u003eДля отключения анимации в компоненте нужно указать [@.disabled]='isDisabled' в нужной ноде компонента. Например:\n\n```html\n\u003cdiv [@.disabled]=\"isDisabled\"\u003e\u003c/div\u003e\n```\n\n\u003c/p\u003e\n\n\u003cp\u003eДля отключения анимации во всем приложении, нужно указать @HostBinding('@.disabled') в корневом компоненте. Например:\n\n```ts\n@Component({\n  selector: \"app-root\",\n  templateUrl: \"app.component.html\",\n  styleUrls: [\"app.component.css\"],\n  animations: [\n    // animation  go here\n  ],\n})\nexport class AppComponent {\n  @HostBinding(\"@.disabled\")\n  public animationsDisabled = true;\n}\n```\n\n  \u003c/p\u003e\n  \u003ch4\u003eДополнительная функциональность для анимаций\u003c/h4\u003e\n  \u003cp\u003eМожно указывать конкретные значения стилей в определенный промежуток времени с помощью \u003cb\u003ekeyframes()\u003c/b\u003e\u003c/p\u003e\n  \u003cp\u003eЕсть возможность запускать анимации параллельно, указав их в функции \u003cb\u003egroup()\u003c/b\u003e. Запускать последовательно с помощью функции \u003cb\u003esequence()\u003c/b\u003e.\u003c/p\u003e\n  \u003cp\u003eАнимацию можно применять к конкретному селектору, который можно указать в параметрах фукнции \u003cb\u003equery()\u003c/b\u003e. Так же. можно управлять анимациями дочерних элементов с помощью \u003cb\u003eanimateChild()\u003c/b\u003e (только для анимаций, описанных с помощью Angular)\u003c/p\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Angular render lifecycle and core environments\n\n\u003cdetails\u003e\n\u003csummary\u003eОбъясните механизм загрузки (bootstrap) Angular-приложения в браузере?\u003c/summary\u003e\n\u003cdiv\u003e\n\u003cbr\u003e\n\u003cp\u003eЗапуск Angular приложения начинается с файла \u003cb\u003emain.ts\u003c/b\u003e. Этот файл содержит в себе примерно следующее:\u003c/p\u003e\n\n```ts\nimport { platformBrowserDynamic } from \"@angular/platform-browser-dynamic\";\nimport { AppModule } from \"./app/app.module\";\n\nconst platform = platformBrowserDynamic();\n\nplatform.bootstrapModule(AppModule);\n```\n\n\u003cp\u003eplatformBrowserDynamic запускает AppModule. После этого, начинает работать логика в AppModule. \u003c/p\u003e\n\u003cp\u003eВ AppModule обычно задается компонент, который будет использоваться для отображения при загрузке. Компонент находится в параметре \u003cb\u003ebootstrap\u003c/b\u003e\u003c/p\u003e\n\n```ts\n@NgModule({\n  imports: [BrowserModule, FormsModule],\n  declarations: [AppComponent],\n  bootstrap: [AppComponent],\n})\nexport class AppModule {}\n```\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак происходит взаимодействие компонентов в Angular (опишите components view)?\u003c/summary\u003e\n\u003cbr\u003e\n\n\u003cdiv\u003e\n  \u003cp\u003eВзаимодействие компонентов может быть: \u003c/p\u003e\n  \u003cul\u003e\n    \u003cli\u003e\u003cb\u003eмежду родительским и дочерним компонентом\u003c/b\u003e - селектор одного компонента объявлен в шаблоне другого\u003c/li\u003e\n    \u003cli\u003e\u003cb\u003eмежду компонентами одного уровня\u003c/b\u003e - селекторы компонентов не вложенные\u003c/li\u003e\n  \u003c/ul\u003e\n  \u003cp\u003e\u003c/p\u003e\n  \u003ch4\u003eСпособы взаимодействия\u003c/h4\u003e\n  \u003col\u003e\n    \u003cli\u003e\n      \u003cp\u003e\u003cb\u003e@Input()/@Output() декораторы свойств\u003c/b\u003e - используются между дочерним и родительским компонентами. В @Input() можно получить значение из родителя. Через @Output() отправить данные из дочернего в родительский компонент.\u003c/p\u003e\n      \u003cp\u003eВ шаблоне родительского компонента ставится селектор дочернего. В селекторе дочернего компонента прописываются атрибуты, через которые будут передаваться данные в переменные @Input()/@Output(). Для обозначения @Input свойства в селекторе нужно прописать \u003cchild [title]='parentTitle'\u003e\u003c/child\u003e. Для обозначения @Output свойства в селекторе нужно прописать \u003cchild (getChanges)='onGetChanges($event)'\u003e\u003c/child\u003e.\u003c/p\u003e\n      \u003cp\u003eВ классе родительского компонента нужно обозначить public свойства/методы, которые будут прописаны в атрибутах дочернего селектора.\u003c/p\u003e\n      \u003cp\u003eВ классе дочернего компонента нужно прописать public свойства с декораторами @Input()/@Output(). Названия свойств должны совпадать с именами в атрибутах дочернего селектора. В @Input() можно передать значения как обычных типов данных (string, number, Array и тп), так и потоки (Subject, Observable). В @Output обычно используется EventEmitter. Через него можно отправить значения в функцию родительского компонента, которая прописана в атрибуте селектора.\u003c/p\u003e\n      \u003cp\u003eПример\u003c/p\u003e\n\n```ts\n@Component({\n  selector: \"parent\",\n  template: `\n    \u003cdiv\u003e\n      \u003cchild [count]=\"value\" (increment)=\"onInstement($event)\"\u003e\u003c/child\u003e\n    \u003c/div\u003e\n  `,\n})\nexport class ParentComponent {\n  public value: number = 0;\n\n  public onIncrement(value: number): void {\n    // actions with child's value\n  }\n}\n\n@Component({\n  selector: \"child\",\n  template: `\n    \u003cdiv\u003e\n      \u003cbutton type=\"button\" (click)=\"onClickIncrement()\"\u003e+1\u003c/button\u003e\n    \u003c/div\u003e\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush, //см пункт \"Какие существуют стратегии обнаружения изменений?\"\n})\nexport class ChildComponent {\n  @Input() public count: number;\n\n  @Output() public increment: EventEmitter\u003cnumber\u003e = new EventEmitter();\n\n  public onClickIncrement(): void {\n    const result = this.count++;\n    this.increment.emit(result);\n  }\n}\n```\n\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003cp\u003e\u003cb\u003e@ViewChild() директива\u003c/b\u003e - получение доступа к свойствам дочернего компонента. В родительском шаблоне нужно указать селектор дочернего. Так же, в родительском компоненте нужно обозначить public свойство с директивой @ViewChild().\u003c/p\u003e\n    \u003cp\u003eПо умолчанию, доступ к свойствам @ViewChild() можно получить в хуке ngAfterViewInit(). Так же, нужно учитывать свойство \u003cb\u003estatic\u003c/b\u003e при использовании @ViewChild(). \u003cb\u003estatic\u003c/b\u003e параметр указывает, когда можно получить доступ к ViewChild() - до или после change detection. Это может понадобится, когда @ViewChild используется в циклах (*ngFor) или доступен только по условию (*ngIf). Если static = false, то доступ можно получить до change detection в хуке ngAfterViewInit(). \u003c/p\u003e\n    \u003cp\u003eПримеры\u003c/p\u003e\n\n```ts\n@Component({\n  selector: \"parent\",\n  template: `\u003cchild #childRef *ngIf=\"isShowChild\"\u003e\u003c/child\u003e`,\n})\nexport class ParentComponent {\n  @ViewChild(\"childRef\", { static: false }) public viewChild: ChildComponent;\n\n  public isShowChild: boolean = false;\n\n  public ngAfterViewInit(): void {\n    console.log(this.viewChild.title);\n  }\n}\n\n@Component({\n  selector: \"parent\",\n  template: `\u003cchild #childRef\u003e\u003c/child\u003e`,\n})\nexport class ParentComponent {\n  @ViewChild(\"childRef\", { static: false }) public viewChild: ChildComponent;\n\n  public ngAfterViewInit(): void {\n    console.log(this.viewChild.title);\n  }\n}\n```\n\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003cp\u003e\u003cb\u003eЧерез сервис\u003c/b\u003e - передача данных между компонентами через единый сервис. Этим способом можно взаимодействовать с компонентами одного уровня. Так же, можно избавиться от иерархии зависимостей и не использовать всплывающие события (Output)\u003c/p\u003e\n    \u003cp\u003eНеобходимо создать общий сервис, который объявляется в параметре providers в общем модуле соединяемых компонентов. В сервисе можно создать public свойства и методы для передачи данных. Можно использовать Observable и Subjects для передачи данных. Пример:\u003c/p\u003e\n\n```ts\n@Injectable()\nexport class CountService {\n  private count$: BehaviorSubject\u003cnumber\u003e = new BehaviorSubject(0);\n\n  public get value$(): Observable\u003cnumber\u003e {\n    return this.count$.asObservable();\n  }\n\n  public get value(): number {\n    return this.count$.getValue();\n  }\n\n  public setState(value: number): void {\n    this.count$.next(value);\n  }\n\n  public reset(): void {\n    this.count$.next(0);\n  }\n}\n\n@Component({\n  selector: \"counter\",\n  template: `\n     value = {{ counter.value$ | async }}  \u003cbr/\u003e\n    \u003cbutton type='button' (click)='counter.setState(counter.value + 1)\u003e+1\u003c/button\u003e\n    \u003cbutton type='button' (click)='counter.setState(counter.value - 1)\u003e-1\u003c/button\u003e\n    \u003cbutton type='reset' (click)='counter.reset()\u003ereset\u003c/button\u003e\n  `,\n})\nexport class CounterComponent {\n  constructor(private counter: CountService) {}\n}\n```\n\n  \u003c/li\u003e\n  \u003c/ol\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКаков жизненный цикл у компонентов?\u003c/summary\u003e\n\u003cdiv\u003e\n\u003cbr\u003e\n\n\u003cb\u003eПосле\u003c/b\u003e создания компонента или директивы через вызов конструктора, Angular вызывает методы жизненного цикла в следующей последовательности в строго определенные моменты:\n\n  \u003cli\u003engOnChanges() - вызывается когда Angular переприсваивает привязанные данные к input properties. Метод получает объект SimpleChanges, со старыми и новыми значениями. Вызывается перед NgOnInit и каждый раз, когда изменяется одно или несколько связанных свойств.\u003c/li\u003e\n  \u003cli\u003engOnInit() - инициализирует директиву/компонент после того, как Angular впервые отобразит связанные свойства и устанавливает входящие параметры.\u003c/li\u003e\n  \u003cli\u003engDoCheck() - при обнаружении изменений, которые Angular не может самостоятельно обнаружить, реагирует на них. \u003c/li\u003e\n  \u003cli\u003engAfterContentInit() - вызывается после того, как Angular спроецирует внешний контент в отображение компонента или отображение с директивой. Вызывается единожды, после первого ngDoCheck().\u003c/li\u003e\n  \u003cli\u003engAfterContentChecked() - реагирует на проверку Angular-ом проецируемого содержимого. Вызывается после ngAfterContentInit() и каждый последующий ngDoCheck().\u003c/li\u003e\n  \u003cli\u003engAfterViewInit() - вызывается после инициализации отображения компонента и дочерних/директив. Вызывается единожды, после первого ngAfterContentChecked().\u003c/li\u003e\n  \u003cli\u003engAfterViewChecked() - реагирует на проверку отображения компонента и дочерних/директив. Вызывается после ngAfterViewInit() и каждый последующий ngAfterContentChecked().\u003c/li\u003e\n  \u003cli\u003engOnDestroy() - после уничтожения директивы/компонента выполняется очистка. Отписывает Observables и отключает обработчики событий, чтобы избежать утечек памяти.\u003c/li\u003e\n  \n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Shadow DOM и как с ним работать в Angular?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Data Binding и какие проблемы связанные с ним вы знаете?\u003c/summary\u003e\n\u003cbr\u003e\n\n\u003cdiv\u003e\n  Angular поддерживает одностороннюю и двустороннюю Data Binding. Это механизм координации частей шаблона с частями компонента. \n  \u003cbr\u003eДобавление специальной разметки сообщает Angular как соединять обе стороны. Следующая диаграмма показывает четыре формы привязки данных.\n  \u003cbr\u003eОдносторонние:\n  \u003cli\u003eОт компонента к DOM с привязкой значения: {{hero.name}}\u003c/li\u003e\n  \u003cli\u003eОт компонента к DOM с привязкой свойства и присвоением значения: [hero]=\"selectedHero\"\u003c/li\u003e\n  \u003cli\u003eОт DOM к компоненту с привязкой на ивент: (click)=\"selectHero(hero)\"\u003c/li\u003e\n  \n  \u003cbr\u003eДвусторонняя в основном используется в template-driven forms, сочетает в себе параметр и ивент. Вот пример, использующий привязку с директивой ngModel.\n  \n  ```html\n    \u003cinput [(ngModel)]=\"hero.name\"\u003e\n  ```\n  \u003cbr\u003eЗдесь значение попадает в input из компонента, как при привязке значения, но при изменении юзером значения новое передается в компонент и переопределяется. \n \n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак вы используете одностороннюю и двухстороннюю привязку данных?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем преимущества и недостатки Regular DOM (Angular) перед Virtual DOM (React)?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое ngZone?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003e\n\n\u003ca href=\"https://angular.io/api/core/NgZone\"\u003eNgZone\u003c/a\u003e - это сервис, который является обёрткой над zone.js, для выполнения кода внутри или вне зоны Angular. Этот сервис создаёт зону с именем angular для автоматического запуска обнаружения изменений, когда выполняются следующие условия:\n\n  \u003cli\u003eКогда выполняется синхронная или асинхронная функция\u003c/li\u003e\n  \u003cli\u003eКогда нет запланированной микро-задачи в очереди\u003c/li\u003e\n\n\u003cbr\u003eНаиболее распространённое применение NgZone — это оптимизация производительности посредством выполнения асинхронной логики вне зоны Angular (метод \u003ccode\u003erunOutsideAngular\u003c/code\u003e), тем самым не вызывая обнаружение изменений или обработку ошибок. Или наоборот, данный сервис может использоваться для выполнения логики внутри зоны (метод \u003ccode\u003erun\u003c/code\u003e), что в конечном итоге приведёт к тому, что Angular снова вызовет обнаружение изменений и при необходимости перерисует представление.\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак обновлять представление, если ваша модель данных обновляется вне 'зоны'?\u003c/summary\u003e\n\u003cbr\u003e\n\n1. Используя метод `ApplicationRef.prototype.tick`, который запустит `change detection` на всем дереве компонентов.\n\n```ts\nimport { Component, ApplicationRef, NgZone } from \"@angular/core\";\n\n@Component({\n  selector: \"app-root\",\n  template: ` \u003ch1\u003eHello, {{ name }}!\u003c/h1\u003e `,\n})\nexport class AppComponent {\n  public name: string = null;\n\n  constructor(private app: ApplicationRef, private zone: NgZone) {\n    this.zone.runOutsideAngular(() =\u003e {\n      setTimeout(() =\u003e {\n        this.name = window.prompt(\"What is your name?\", \"Jake\");\n        this.app.tick();\n      }, 5000);\n    });\n  }\n}\n```\n\n2. Используя метод `NgZone.prototype.run`, который также запустит `change detection` на всем дереве.\n\n```ts\nimport { Component, NgZone } from \"@angular/core\";\nimport { SomeService } from \"./some.service\";\n\n@Component({\n  selector: \"app-root\",\n  template: ` \u003ch1\u003eHello, {{ name }}!\u003c/h1\u003e `,\n  providers: [SomeService],\n})\nexport class AppComponent {\n  public name: string = null;\n\n  constructor(private zone: NgZone, private service: SomeService) {\n    this.zone.runOutsideAngular(() =\u003e {\n      this.service.getName().then((name: string) =\u003e {\n        this.zone.run(() =\u003e (this.name = name));\n      });\n    });\n  }\n}\n```\n\nМетод `run` под капотом сам вызывает `tick`, а параметром принимает функцию, которую нужно выполнить перед `tick`. То есть:\n\n```ts\nthis.zone.run(() =\u003e (this.name = name));\n\n// идентично\n\nthis.name = name;\nthis.app.tick();\n```\n\n3. Используя метод `ChangeDetectorRef.prototype.detectChanges`, который запустит `change detection` на текущем компоненте и дочерних.\n\n```ts\nimport { Component, NgZone, ChangeDetectorRef } from \"@angular/core\";\n\n@Component({\n  selector: \"app-root\",\n  template: ` \u003ch1\u003eHello, {{ name }}!\u003c/h1\u003e `,\n})\nexport class AppComponent {\n  public name: string = null;\n\n  constructor(private zone: NgZone, private ref: ChangeDetectorRef) {\n    this.zone.runOutsideAngular(() =\u003e {\n      this.name = window.prompt(\"What is your name?\", \"Jake\");\n      this.ref.detectChanges();\n    });\n  }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое EventEmitter и как подписываться на события?\u003c/summary\u003e\n\u003cdiv\u003e\n\u003cbr\u003e\nИспользуется в директивах и компонентах для подписки на пользовательские ивенты синхронно или асинхронно, и регистрации обработчиков для этих ивентов.\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Change Detection, как работает Change Detection Mechanism?\u003c/summary\u003e\n\n\u003ch4\u003e1. Change Detection\u003c/h4\u003e\n  \nChange Detection - процесс синхронизации модели с представлением. В Angular поток информации однонаправленный, даже при использовании `ngModel` для реализации двустороннего связывания, которая является синтаксическим сахаром поверх однонаправленного потока.\n\n\u003ch4\u003e2. Change Detection Mechanism \u003c/h4\u003e\n\nChange Detection Mechanism - продвигается только вперед и никогда не оглядывается назад, начиная с корневого (рут) компонента до последнего. В этом и есть смысл одностороннего потока данных. Архитектура Angular приложения очень проста — дерево компонентов. Каждый компонент указывает на дочерний, но дочерний не указывает на родительский. Односторонний поток устраняет необходимость `$digest` цикла.\n\n\u003cbr\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКакие существуют стратегии обнаружения изменений?\u003c/summary\u003e\n\u003cbr\u003e\n\nВсего есть две стратегии - `Default` и `OnPush`. Если все компоненты используют первую стратегию, то `Zone` проверяет все дерево независимо от того, где произошло изменение. Чтобы сообщить Angular, что мы будем соблюдать условия повышения производительности нужно использовать стратегию обнаружения изменений `OnPush`. Это сообщит Angular, что наш компонент зависит только от входных данных и любой объект, который передается ему должен считаться immutable. Это все построено на принципе автомата Мили, где текущее состояние зависит только от входных значений.\n\n\u003cbr\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eСколько Change Detector(ов) может быть во всем приложении?\u003c/summary\u003e\n\u003cbr\u003e\nУ каждого компонента есть свой Change Detector, все Change Detector(ы) наследуются от AbstractChangeDetector.  \n\u003cbr\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eОсновное отличие constructor от ngOnInit?\u003c/summary\u003e\n\u003cbr\u003e\n  \nКонструктор сам по себе является фичей самого класса, а не Angular. Основная разница в том, что Angular запустит `ngOnInit`, после того, как закончит настройку компонента, то есть, это сигнал, благодаря которому свойства `@Input()` и другие байндинги, и декорируемые свойства доступны в `ngOnInit`, но не определены внутри конструктора, по дизайну.\n\n\u003cbr\u003e\n\u003c/details\u003e\n\n##### RxJS\n\n\u003cdetails\u003e\n\u003csummary\u003eДля чего нужен RxJS и какую проблему он решает?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Observable?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003eObservable— это наблюдатель, который подписывается и реагирует на все события до момента отписки. \n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чём разница между Observable и Promise?\u003c/summary\u003e\n\u003cdiv\u003e\n \u003cbr\u003e\n \u003cp\u003ePromise обрабатывает одно значение по завершению асинхронной операции, вне зависимости от ее исхода, и не поддерживают отмену операции.\u003c/p\u003e\n \u003cp\u003eObservable же является потоком, и позволяет передавать как ноль, так и несколько событий, когда callback вызывается для каждого события.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чём разница между Observable и BehaviorSubject/Subject (Higher Order Observables)?\u003c/summary\u003e\n\u003cdiv\u003e\n\u003cbr\u003e\n\n\u003cp\u003eSubjects - специальные Observable. Представьте, что есть спикер с микрофоном, который выступает в комнате, полной людей. \nЭто и есть Subjects, их сообщение передается сразу нескольким получателям. Обычные же Observables можно сравнить с разговором 1 на 1.\u003c/p\u003e\n\n\u003cul\u003e\n    \u003cli\u003eSubject - является multicast, то есть может передавать значение сразу нескольким подписчикам.\u003c/li\u003e\n    \u003cli\u003eBehaviorSubject - требует начальное значение и передает текущее значение новым подпискам.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем разница между Subject, BehaviorSubject, ReplaySubject, AsyncSubject?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003e\n\n  \u003cul\u003e\n    \u003cli\u003eSubject - не хранит свои предыдущие состояния, зритель получает информацию только тогда, когда Subject сгенерирует новое событие, используя метод \u003ccode\u003e.next()\u003c/code\u003e.\u003c/li\u003e\n    \u003cli\u003eBehaviorSubject - при подписке поведенческий Subject уведомляет своего зрителя о последнем произошедшем в нём событии или, если в Subject-е не происходило событий, создаёт для зрителя событие с изначальной информацией, которая передаётся при создании Subject-а.\u003c/li\u003e\n    \u003cli\u003eReplaySubject - при подписке повторяющийся Subject уведомляет своего нового зрителя о всех произошедшем в нём событиях с момента создания. Для оптимизации при создании повторяющегося Subject-а можно передать число последних событий, которые будут повторяться для каждого нового зрителя. Стоит отметить, что создание ReplaySubject-а c числом повторяющихся событий равное 1 эквивалетно созданию BehaviorSubject-а.\u003c/li\u003e\n    \u003cli\u003eAsyncSubject - асинхронный Subject уведомляет своих зрителей только о последнем произошедшем событии и только когда Subject успешно завершается. Если AsyncSubject завершится ошибкой, его зрители будут уведомлены только об ошибке.\n    \u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чём разница между операторами switchMap, mergeMap, concatMap?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003e\n  \u003cul\u003e  \n      \u003cli\u003eswitchMap - отменит подписку на Observable, возвращенный ее аргументом project, как только он снова вызовет ее в новом элементе.\u003c/li\u003e\n      \u003cli\u003emergeMap - в отличие от switchMap позволяет реализовать одновременно несколько внутренних подписок. \u003c/li\u003e\n      \u003cli\u003econcatMap - последовательно обрабатывает каждое событие, в отличие от mergeMap.\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак бы вы кешировали наблюдаемые данные из потоков (stream)?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Angular data flow\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Dependency Injection?\u003c/summary\u003e\n\u003cdiv\u003e\n\u003cbr\u003eЭто важный паттерн шаблон проектирования приложений. В Angular внедрение зависимостей реализовано из-под капота.\u003cbr\u003e\n\u003cbr\u003eЗависимости - это сервисы или объекты, которые нужны классу для выполнения своих функций. DI -позволяет запрашивать зависимости от внешних источников.\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Singleton Service и с какой целью его используют в Angular?\u003c/summary\u003e\n\u003cdiv\u003e\n\u003cbr\u003e\n\nЭто сервисы, объявленные в приложении и имеющие один экземпляр на все приложение.\nЕго можно объявить двумя способами:\n\n  \u003cli\u003eОбъявить его @Injectable(root)\u003c/li\u003e\n  \u003cli\u003eВключить его в AppModule в providers, либо в единственный модуль импортируемый в AppModule.\u003c/li\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак можно определить свой обработчик ErrorHandler, Logging, Cache в Angular?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое управление состоянием приложения?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем отличие между NGRX, NGXS, Akita и какую проблему они решают?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Angular with Backend integrations\n\n\u003cdetails\u003e\n\u003csummary\u003eКакими способами можно взаимодействовать с API бэкенда, что требуется для проксирования запросов?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003e\n  \u003cb\u003eВзаимодействие с API\u003c/b\u003e\n\nВ экосистеме ангуляр существует пакет для общения с сервером\n(@angular/common/http), которого достаточно для повседневной разработки. Его интерфейс основан на rxjs потоках, поэтому его легко использовать для работы с потоками данных в приложении.\n\u003cbr\u003e\n\nКроме этого, как и в ванильной версии javascript, можно использовать XMLHttpRequest, fetch API, axios(или многие другие библиотеки), но их использование вместо встроенного клиента, считается неоправданным и всячески возбраняется.\n\nСуществуют и другие способы взаимодействия с сервером(см. Веб-сокеты), но для них не существует каноничных встроенных библиотек, поэтому используются сторонние библиотеки или собственные реалиации. Хорошей практикой здесь будет привести интерфейс построенный на промисах и обратных вызовах(callback) к интерфейсу основанному на rxjs потоках, для естественного использования в экосистеме Angular.\n\n  \u003cbr\u003e\n  \u003cb\u003eProxy\u003c/b\u003e\n\nЧтобы тестировать взаимодействие приложения с сервером, который должен находиться на том же домене, используется \u003ca href=\"https://angular.io/guide/build#proxying-to-a-backend-server\"\u003e функциональность в Angular CLI\u003c/a\u003e для этого нужно создать файл с конфигурацией прокси, где будут указаны:\n\n  \u003cul\u003e\n    \u003cli\u003eКонтекст для проксирования\u003c/li\u003e\n    \u003cli\u003eСсылка на работающий экземпляр API\u003c/li\u003e\n    \u003cli\u003esecure: false для работы в тестовой среде без сертификатов\u003c/li\u003e\n  \u003c/ul\u003e\n\nТакже большинство серверов не настроены для работы с разными доменами(\u003ca href=\"https://developer.mozilla.org/ru/docs/Web/HTTP/CORS\"\u003eCORS\u003c/a\u003e), поэтому для корректной работы на API сервере, необходимо явно указать с какого домена(ов) можно принимать запросы.\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое HTTP Interceptors?\u003c/summary\u003e\n\u003cbr\u003e\n\u003cbr\u003e\nInterceptor (перехватчик) - просто причудливое слово для функции, которая получает запросы / ответы до того, как они будут обработаны / отправлены на сервер. Нужно использовать перехватчики, если имеет смысл предварительно обрабатывать многие типы запросов одним способом. Например нужно для всех запросов устанавливать хедер авторизации `Bearer`:\n\ntoken.interceptor.ts\n\n```ts\nimport { Injectable } from \"@angular/core\";\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n  HttpEvent,\n} from \"@angular/common/http\";\nimport { Observable } from \"rxjs/Observable\";\n\n@Injectable()\nexport class TokenInterceptor implements HttpInterceptor {\n  public intercept(\n    req: HttpRequest\u003cany\u003e,\n    next: HttpHandler\n  ): Observable\u003cHttpEvent\u003cany\u003e\u003e {\n    const token = localStorage.getItem(\"token\") as string;\n\n    if (token) {\n      req = req.clone({\n        setHeaders: {\n          Authorization: `Bearer ${token}`,\n        },\n      });\n    }\n\n    return next.handle(req);\n  }\n}\n```\n\nИ регистрируем перехватчик как синглтон в провайдерах модуля:\n\napp.module.ts\n\n```ts\nimport { NgModule } from \"@angular/core\";\nimport { BrowserModule } from \"@angular/platform-browser\";\nimport { HTTP_INTERCEPTORS } from \"@angular/common/http\";\nimport { AppComponent } from \"./app.component\";\nimport { TokenInterceptor } from \"./token.interceptor\";\n\n@NgModule({\n  imports: [BrowserModule],\n  declarations: [AppComponent],\n  bootstrap: [AppComponent],\n  providers: [\n    {\n      provide: HTTP_INTERCEPTORS,\n      useClass: TokenInterceptor,\n      multi: true, // \u003c--- может быть зарегистрирован массив перехватчиков\n    },\n  ],\n})\nexport class AppModule {}\n```\n\n\u003cbr\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак использовать Json Web Tokens для аутентификации при разработке на Angular?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак обрабатываются атаки XSS и CSRF в Angular?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Angular routing\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое роутинг и как его создать в Angular?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003e\n  Роутинг позволяет реализовать навигацию от одного view приложения к другому при работе пользователя с приложением.\n  \u003cbr\u003eЭто реализовано через взаимодействие с адресной строкой, Angular Router интерпретирует ее как инструкцию по переходу между view. Возможна передача параметров вспомогательному компоненту для конкретизирования предоставляемого контента. Навигация может осуществлять по ссылкам на странице, кнопкам или другим элементам, как кнопки \"вперед-назад\" в браузере.\n  \u003cbr\u003eДля создания роутинга первым делом необходимо импортировать \"RouterModule\" и \"Routes\" в AppModule.\n  \u003cbr\u003eЗатем необходимо реализовать конфигурацию по приложению, определить path и относящие к ним компоненты, и в метод RouterModule.forRoot() передать конфигурацию.\n  \u003cbr\u003eНаконец необходимо добавить routerLink в шаблон.\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКаков жизненный цикл у Angular Router?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003e\n  \u003cp\u003e\n    \u003cimg src='https://susdev.ru/wp-content/uploads/2019/02/router-navigation-lifecycle.png'  alt=\"\"/\u003e\n    \u003ca href='https://susdev.ru/angular-router-series-router-navigation-cycle/'\u003eИсточник информации\u003c/a\u003e\n  \u003c/p\u003e\n  \u003cp\u003e\n    \u003col\u003e\n      \u003cli\u003e\u003cb\u003eNavigationStart\u003c/b\u003e - начало навигации. Возникает во время нажатия на директиву \u003cb\u003erouter link\u003c/b\u003e, вызове функций \u003cb\u003enavigate\u003c/b\u003e и \u003cb\u003enavigateByUrl\u003c/b\u003e\u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eRoutesRecognized\u003c/b\u003e - cопоставление URL-адресов и редиректы. Роутер сопоставляет URL-адрес навигации из первого события с одним из свойств path в конфигурации, применяя любые редиректы по-пути.\u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eGuardsCheckStart, GuardsCheckEnd\u003c/b\u003e - функции, которые использует роутер для определения может ли он выполнить навигацию. Пример:\n\n```ts\n// router configuration\nconst config = {\n  path: \"users\",\n  /* ... */\n  canActivate: [CanActivateGuard],\n};\n\nclass Guard {\n  // router guard implementation\n  canActivate(\n    route: ActivatedRouteSnapshot,\n    state: RouterStateSnapshot\n  ): boolean {\n    return this.auth.isAuthorized(route.queryParams.login);\n  }\n}\n```\n\n  \u003cbr /\u003e\n\nЕсли вызов `isAuthorized(route.queryParams.login)` возвращает true, guard завершится успехом. В противном случае guard упадет, роутер сгенерирует событие `NavigationCancel` и отменит всю дальнейшую навигацию.\n\u003cbr /\u003e\n\nДругие guard включают `canLoad` (должен ли модуль быть лениво загружен или нет). `canActivateChild` и `canDeactivate` (которые полезны для предотвращения ухода пользователя со страницы, например, при заполнении формы).\n\n  \u003c/li\u003e\n  \u003cli\u003e\u003cb\u003eResolveStart, ResolveEnd\u003c/b\u003e - функции, которые мы можем использовать для подгрузки данных во время навигации. Например:\n\n```ts\n// router configuration\nconst config = {\n  path: \"users\",\n  /* ... */\n  resolve: { users: UserResolver },\n};\n\n// router resolver implementation\nexport class UserResolver implements Resolve\u003cObservable\u003cany\u003e\u003e {\n  constructor(private userService: MockUserDataService) {}\n  resolve(): Observable\u003cany\u003e {\n    return this.userService.getUsers();\n  }\n}\n```\n\n\u003cbr/\u003e\n\nРезультат, то есть данные, будет положен в `data` объект сервиса `ActivatedRoute` с ключом `users`. Данная информация может быть прочитаны с помощью подписки на `data` `observable`.\n\n```ts\nexport class UsersComponent implements OnInit {\n  public users = [];\n  constructor(private route: ActivatedRoute) {}\n  ngOnInit() {\n    this.route.data\n      .pipe(first())\n      .subscribe((data) =\u003e (this.users = data.users));\n  }\n}\n```\n\n  \u003c/li\u003e\n  \u003cli\u003e\u003cb\u003eActivationStart, ActivationEnd, ChildActivationStart, ChildActivationEnd\u003c/b\u003e - события, во время которых активируются компоненты и отображаются их с помощью \u003crouter-outlet\u003e.Роутер может извлечь необходимую информацию о компоненте из дерева ActivatedRouteSnapshots. Он был построен в предыдущие шаги навигационного цикла.\u003c/li\u003e\n  \u003cli\u003e\u003cb\u003eUpdating the URL\u003c/b\u003e - последний шаг в навигационном цикле — это обновление URL-адреса в address bar\u003c/li\u003e\n  \u003c/ol\u003e\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое ленивая загрузка (Lazy-loading) и для чего она используется?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем разница между Routing и Navigation?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак загрузить данные до того как активируется роут?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Angular Forms (also big ui enterprise)\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое FormGroup и FormControl и для чего они используются?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003e\n  \u003cli\u003eFormControl - отслеживает значение и статус валидации отдельного элемента формы.\u003c/li\u003e\n  \u003cli\u003eFormGroup - отслеживает состояние и статус валидации группы FormControl \u003c/li\u003e\n  \u003cbr\u003eОни используются для создания и работы с формами.\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое реактивные формы в Angular?\u003c/summary\u003e\n\u003cdiv\u003e\n  Реактивные формы обеспечивают управляемый моделями подход к обработке входных данных форм, значения которых могут меняться со временем. Они строятся вокруг наблюдаемых потоков, где входные данные и значения форм предоставляются в виде потоков входных значений, к которым можно получить синхронный доступ. \n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак применять валидацию для простых и сложных форм?\u003c/summary\u003e\n\u003cdiv\u003e\n  В реактивных формах валидация реализуется в компоненте. Есть два типа валидаторов: синхронные и асинхронные.\n  \u003cbr\u003eМожно использовать встроенные валидаторы, либо создать свои. Валидаторы добавляются \n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Build environments\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем разница между Angular CLI и Webpack Development Environment?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое JIT и AOT, в чем их отличия и каковы сферы применения?\u003c/summary\u003e\n\u003cdiv\u003e\n  \u003cbr\u003e\n  \u003cp\u003eAngular приложение можно скомпилировать с помощью команд \u003cb\u003eng serve\u003c/b\u003e и \u003cb\u003eng build\u003c/b\u003e. При этом, можно работать с разными видами компиляции:\n  \u003cul\u003e\n    \u003cli\u003e \u003cb\u003eJIT\u003c/b\u003e - (Just-In-Time compilation) - компиляция \"на лету\", динамическая компиляция. В Angular используется по умолчанию.\u003c/li\u003e\n    \u003cli\u003e \u003cb\u003eAOT\u003c/b\u003e -  (Ahead-Of-Time compilation) - компиляции перед исполнением.\u003c/li\u003e\n  \u003c/ul\u003e\n  \u003cp\u003eОсновные различия:\u003c/p\u003e\n  \u003ctable\u003e\n    \u003cthead\u003e\n      \u003ctr\u003e\u003ctd\u003eПараметры\u003c/td\u003e\u003ctd\u003eJIT\u003c/td\u003e\u003ctd\u003eAOT\u003c/td\u003e\u003c/tr\u003e\n    \u003c/thead\u003e\n    \u003ctbody\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eКогда компилируется\u003c/td\u003e\n        \u003ctd\u003eв момент запуска приложения в браузере\u003c/td\u003e\n        \u003ctd\u003eв момент сборки приложения\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eРекомендуется использовать для\u003c/td\u003e\n        \u003ctd\u003eлокальной разработки\u003c/td\u003e\n        \u003ctd\u003eсоздания продуктовой сборки\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eКак включить\u003c/td\u003e\n        \u003ctd\u003eНе нужно выставлять дополнительных флагов\u003c/td\u003e\n        \u003ctd\u003eНужно добавить флаг --aot или --prod\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eСкорость\u003c/td\u003e\n        \u003ctd\u003eСкорость компиляции быстрее, загрузка в браузере дольше\u003c/td\u003e\n        \u003ctd\u003eСкорость компиляции дольше, загрузка в браузере быстрее\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eРазмер бандла\u003c/td\u003e\n        \u003ctd\u003eБандл имеет большой размер из-за включенного в бандл компилятора.\u003c/td\u003e\n        \u003ctd\u003eБандл имеет небольшой размер, тк содержит полностью скомпилированный и оптимизированный код.\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eВыявление ошибок\u003c/td\u003e\n        \u003ctd\u003eОшибки отобразятся во время запуска приложения в браузере\u003c/td\u003e\n        \u003ctd\u003eВыявление ошибок во время компиляции\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eРабота с файлами\u003c/td\u003e\n        \u003ctd\u003eМожет компилировать только измененные файлы отдельно\u003c/td\u003e\n        \u003ctd\u003eКомпилирует сразу все файлы приложения\u003c/td\u003e\n      \u003c/tr\u003e\n    \u003c/tbody\u003e\n  \u003c/table\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Test development\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Unit-тестирование, интеграционное, e2e-тестирование (End-to-End) и как оно применяется в Angular?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЧто такое Karma, Jasmine (зачем их используют совместно при разработке на Angular)?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем разница между Jest и Karma?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eВ чем разница между Protractor и Cypress?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eКак протестировать входные параметры и всплывающие события компонентов?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n\n##### Code convention\n\n\u003cdetails\u003e\n\u003csummary\u003eТребования к написанию кода на TypeScript\u003c/summary\u003e\n\u003cdiv\u003e\n  \n\u003cbr\u003e\n\nНа самом деле требования бывают разные и зависят от команды к команде.\nСамые эффективные для себя считаю использование модификаторов доступа и принудительного указания типов данных для всех переменных,\nметодов и членов класса, которые вы используете в коде. Желательно все необходимые правила конвенции кода настраивать в ESLint.\n\n```ts\n// my.ts\nexport interface My {}\n\n// my-impl.ts\nexport class MyImp implements My {\n  public field: string;\n\n  public myMethod(): void {\n    // ...\n  }\n\n  private myProtectedMethod(): Date {\n    return new Date();\n  }\n\n  private myPrivateMethod(): MyClassImpl {\n    // ...\n\n    return this;\n  }\n}\n```\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eЗачем нужен ESLint (TSLint) и Prettier?\u003c/summary\u003e\n\u003cdiv\u003e\n  in progress..\n\u003c/div\u003e\n\u003c/details\u003e\n","funding_links":[],"categories":["Others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAngular-RU%2Fangular-ru-interview-questions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAngular-RU%2Fangular-ru-interview-questions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAngular-RU%2Fangular-ru-interview-questions/lists"}