@anglr/select 17.2.0 → 18.0.0-beta.20260805050455

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/.claude/skills/angular-developer/SKILL.md +130 -130
  2. package/.claude/skills/angular-developer/references/angular-animations.md +160 -160
  3. package/.claude/skills/angular-developer/references/angular-aria.md +410 -410
  4. package/.claude/skills/angular-developer/references/cli.md +86 -86
  5. package/.claude/skills/angular-developer/references/component-harnesses.md +59 -59
  6. package/.claude/skills/angular-developer/references/component-styling.md +91 -91
  7. package/.claude/skills/angular-developer/references/components.md +117 -117
  8. package/.claude/skills/angular-developer/references/creating-services.md +97 -97
  9. package/.claude/skills/angular-developer/references/data-resolvers.md +69 -69
  10. package/.claude/skills/angular-developer/references/define-routes.md +67 -67
  11. package/.claude/skills/angular-developer/references/defining-providers.md +72 -72
  12. package/.claude/skills/angular-developer/references/di-fundamentals.md +120 -120
  13. package/.claude/skills/angular-developer/references/e2e-testing.md +66 -66
  14. package/.claude/skills/angular-developer/references/effects.md +83 -83
  15. package/.claude/skills/angular-developer/references/hierarchical-injectors.md +43 -43
  16. package/.claude/skills/angular-developer/references/host-elements.md +80 -80
  17. package/.claude/skills/angular-developer/references/injection-context.md +63 -63
  18. package/.claude/skills/angular-developer/references/inputs.md +101 -101
  19. package/.claude/skills/angular-developer/references/linked-signal.md +59 -59
  20. package/.claude/skills/angular-developer/references/loading-strategies.md +61 -61
  21. package/.claude/skills/angular-developer/references/mcp.md +106 -106
  22. package/.claude/skills/angular-developer/references/migrations.md +30 -30
  23. package/.claude/skills/angular-developer/references/navigate-to-routes.md +69 -69
  24. package/.claude/skills/angular-developer/references/outputs.md +86 -86
  25. package/.claude/skills/angular-developer/references/reactive-forms.md +122 -122
  26. package/.claude/skills/angular-developer/references/rendering-strategies.md +44 -44
  27. package/.claude/skills/angular-developer/references/resource.md +77 -77
  28. package/.claude/skills/angular-developer/references/route-animations.md +56 -56
  29. package/.claude/skills/angular-developer/references/route-guards.md +52 -52
  30. package/.claude/skills/angular-developer/references/router-lifecycle.md +45 -45
  31. package/.claude/skills/angular-developer/references/router-testing.md +87 -87
  32. package/.claude/skills/angular-developer/references/show-routes-with-outlets.md +68 -68
  33. package/.claude/skills/angular-developer/references/signal-forms.md +897 -897
  34. package/.claude/skills/angular-developer/references/signals-overview.md +94 -94
  35. package/.claude/skills/angular-developer/references/tailwind-css.md +69 -69
  36. package/.claude/skills/angular-developer/references/template-driven-forms.md +114 -114
  37. package/.claude/skills/angular-developer/references/testing-fundamentals.md +66 -66
  38. package/.github/instructions/typescript/code-conventions.md +7 -7
  39. package/.github/instructions/typescript/comments.md +40 -40
  40. package/.github/instructions/typescript/formatting.md +41 -41
  41. package/.github/instructions/typescript/naming-conventions.md +6 -6
  42. package/es2022/extensions/src/extensions/getSearch.js.map +1 -1
  43. package/es2022/extensions/src/extensions/getSelectedOption.js.map +1 -1
  44. package/es2022/extensions/src/extensions/getSelectedOptions.js.map +1 -1
  45. package/es2022/extensions/src/extensions/getValue.js.map +1 -1
  46. package/es2022/extensions/src/extensions/setReadonly.js.map +1 -1
  47. package/es2022/extensions/src/extensions/setValue.js.map +1 -1
  48. package/es2022/extensions/src/index.js.map +1 -1
  49. package/es2022/src/components/index.js.map +1 -1
  50. package/es2022/src/components/option/option.component.js.map +1 -1
  51. package/es2022/src/components/optionGroup/optgroup.component.js.map +1 -1
  52. package/es2022/src/components/select/select.component.js +2 -2
  53. package/es2022/src/components/select/select.component.js.map +1 -1
  54. package/es2022/src/decorators/index.js.map +1 -1
  55. package/es2022/src/decorators/mergeOptionsAsSignal/mergeOptionsAsSignal.decorator.js.map +1 -1
  56. package/es2022/src/directives/highlightInstance/highlightInstance.directive.js.map +1 -1
  57. package/es2022/src/directives/highlightSearch/highlightSearch.directive.js.map +1 -1
  58. package/es2022/src/directives/highlightText/highlightText.directive.js.map +1 -1
  59. package/es2022/src/directives/index.js.map +1 -1
  60. package/es2022/src/directives/normalStateTagTemplate/normalStateTagTemplate.directive.js.map +1 -1
  61. package/es2022/src/directives/normalStateTemplate/normalStateTemplate.directive.js.map +1 -1
  62. package/es2022/src/directives/optionGroupTemplate/optionGroupTemplate.directive.js.map +1 -1
  63. package/es2022/src/directives/optionTemplate/optionTemplate.directive.js.map +1 -1
  64. package/es2022/src/directives/selectAbsolute/selectAbsolute.directive.js.map +1 -1
  65. package/es2022/src/directives/selectControlValueAccessor/selectControlValueAccessor.directive.js.map +1 -1
  66. package/es2022/src/directives/selectEdit/selectEdit.directive.js.map +1 -1
  67. package/es2022/src/directives/selectFormControl/selectFormControl.directive.js.map +1 -1
  68. package/es2022/src/directives/selectMultipleKeepPopup/selectMultipleKeepPopup.directive.js.map +1 -1
  69. package/es2022/src/directives/selectNoCarret/selectNoCarret.directive.js.map +1 -1
  70. package/es2022/src/directives/selectPlaceholder/selectPlaceholder.directive.js.map +1 -1
  71. package/es2022/src/directives/withDirectAccess/withDirectAccess.directive.js.map +1 -1
  72. package/es2022/src/index.js.map +1 -1
  73. package/es2022/src/interfaces/index.js.map +1 -1
  74. package/es2022/src/interfaces/initState/initState.interface.js.map +1 -1
  75. package/es2022/src/interfaces/keyboardAction/keyboardAction.interface.js.map +1 -1
  76. package/es2022/src/interfaces/normalStateContext/normalStateContext.interface.js.map +1 -1
  77. package/es2022/src/interfaces/normalStateTagContext/normalStateTagContext.interface.js.map +1 -1
  78. package/es2022/src/interfaces/optionsGatherer/optionsGatherer.interface.js.map +1 -1
  79. package/es2022/src/interfaces/pluginDescription/pluginDescription.interface.js.map +1 -1
  80. package/es2022/src/interfaces/pluginOptions/pluginOptions.interface.js.map +1 -1
  81. package/es2022/src/interfaces/plugins/index.js.map +1 -1
  82. package/es2022/src/interfaces/plugins/interactions/interactions.interface.js.map +1 -1
  83. package/es2022/src/interfaces/plugins/keyboardHandler/keyboardHandler.interface.js.map +1 -1
  84. package/es2022/src/interfaces/plugins/keyboardHandler/simpleKeyboardHandler.interface.js.map +1 -1
  85. package/es2022/src/interfaces/plugins/liveSearch/editLiveSearch.interface.js.map +1 -1
  86. package/es2022/src/interfaces/plugins/liveSearch/filterLiveSearch.interface.js.map +1 -1
  87. package/es2022/src/interfaces/plugins/liveSearch/liveSearch.interface.js.map +1 -1
  88. package/es2022/src/interfaces/plugins/normalState/editNormalState.interface.js.map +1 -1
  89. package/es2022/src/interfaces/plugins/normalState/normalState.interface.js.map +1 -1
  90. package/es2022/src/interfaces/plugins/normalState/simpleNormalState.interface.js.map +1 -1
  91. package/es2022/src/interfaces/plugins/optionsHandler/optionsHandler.interface.js.map +1 -1
  92. package/es2022/src/interfaces/plugins/optionsHandler/simpleOptionsHandler.interface.js.map +1 -1
  93. package/es2022/src/interfaces/plugins/popup/popup.interface.js.map +1 -1
  94. package/es2022/src/interfaces/plugins/popup/simplePopup.interface.js.map +1 -1
  95. package/es2022/src/interfaces/plugins/positioner/commonPositioner.interface.js.map +1 -1
  96. package/es2022/src/interfaces/plugins/positioner/popoverPositioner.interface.js.map +1 -1
  97. package/es2022/src/interfaces/plugins/positioner/positioner.interface.js.map +1 -1
  98. package/es2022/src/interfaces/plugins/readonlyState/readonlyState.interface.js.map +1 -1
  99. package/es2022/src/interfaces/plugins/valueHandler/dynamicValueHandler.interface.js.map +1 -1
  100. package/es2022/src/interfaces/plugins/valueHandler/valueHandler.interface.js.map +1 -1
  101. package/es2022/src/interfaces/popupContext/popupContext.interface.js.map +1 -1
  102. package/es2022/src/interfaces/selectApi/selectApi.interface.js.map +1 -1
  103. package/es2022/src/interfaces/selectBusOptions/selectBusOptions.interface.js.map +1 -1
  104. package/es2022/src/interfaces/selectCssClasses/selectCssClasses.interface.js.map +1 -1
  105. package/es2022/src/interfaces/selectEvent/selectEvent.interface.js.map +1 -1
  106. package/es2022/src/interfaces/selectEvents/selectEvents.interface.js.map +1 -1
  107. package/es2022/src/interfaces/selectOption/selectOption.interface.js.map +1 -1
  108. package/es2022/src/interfaces/selectOptionGroup/selectOptionGroup.interface.js.map +1 -1
  109. package/es2022/src/interfaces/selectOptionState/selectOptionState.interface.js.map +1 -1
  110. package/es2022/src/interfaces/selectOptionStateSyntetic/selectOptionStateSyntetic.interface.js.map +1 -1
  111. package/es2022/src/interfaces/selectOptions/selectOptions.interface.js.map +1 -1
  112. package/es2022/src/interfaces/selectPlugin/selectPlugin.interface.js.map +1 -1
  113. package/es2022/src/interfaces/selectPluginTypes/selectPluginTypes.interface.js.map +1 -1
  114. package/es2022/src/interfaces/tempValue/tempValue.interface.js.map +1 -1
  115. package/es2022/src/interfaces/templateGatherer/templateGatherer.interface.js.map +1 -1
  116. package/es2022/src/interfaces/visualPluginOptions/visualPluginOptions.interface.js.map +1 -1
  117. package/es2022/src/misc/classes/codeOptionsGatherer/codeOptionsGatherer.interface.js.map +1 -1
  118. package/es2022/src/misc/classes/index.js.map +1 -1
  119. package/es2022/src/misc/classes/selectBus/selectBus.js.map +1 -1
  120. package/es2022/src/misc/classes/selectPluginInstances/selectPluginInstances.js.map +1 -1
  121. package/es2022/src/misc/enums.js.map +1 -1
  122. package/es2022/src/misc/providers.js.map +1 -1
  123. package/es2022/src/misc/tokens.js.map +1 -1
  124. package/es2022/src/misc/types.js.map +1 -1
  125. package/es2022/src/misc/utils.js.map +1 -1
  126. package/es2022/src/modules/index.js.map +1 -1
  127. package/es2022/src/modules/select.module.js.map +1 -1
  128. package/es2022/src/pipes/addNewOption/addNewOption.pipe.js.map +1 -1
  129. package/es2022/src/pipes/displayOptionValue/displayOptionValue.pipe.js.map +1 -1
  130. package/es2022/src/pipes/displayValue/displayValue.pipe.js.map +1 -1
  131. package/es2022/src/pipes/getPlugin/getPlugin.pipe.js.map +1 -1
  132. package/es2022/src/pipes/groupedListOptions/groupedListOptions.pipe.js.map +1 -1
  133. package/es2022/src/pipes/hasValue/hasValue.pipe.js.map +1 -1
  134. package/es2022/src/pipes/index.js.map +1 -1
  135. package/es2022/src/pipes/optionCssClasses/optionCssClasses.pipe.js.map +1 -1
  136. package/es2022/src/plugins/index.js.map +1 -1
  137. package/es2022/src/plugins/interactions/index.js.map +1 -1
  138. package/es2022/src/plugins/interactions/simpleInteractions/simpleInteractions.component.js.map +1 -1
  139. package/es2022/src/plugins/keyboardHandler/index.js.map +1 -1
  140. package/es2022/src/plugins/keyboardHandler/simpleKeyboardHandler/simpleKeyboardHandler.component.js.map +1 -1
  141. package/es2022/src/plugins/liveSearch/editLiveSearch/editLiveSearch.component.js +2 -2
  142. package/es2022/src/plugins/liveSearch/editLiveSearch/editLiveSearch.component.js.map +1 -1
  143. package/es2022/src/plugins/liveSearch/filterLiveSearch/filterLiveSearch.component.js.map +1 -1
  144. package/es2022/src/plugins/liveSearch/index.js.map +1 -1
  145. package/es2022/src/plugins/liveSearch/noLiveSearch/noLiveSearch.component.js.map +1 -1
  146. package/es2022/src/plugins/normalState/editNormalState/editNormalState.component.js +3 -2
  147. package/es2022/src/plugins/normalState/editNormalState/editNormalState.component.js.map +1 -1
  148. package/es2022/src/plugins/normalState/index.js.map +1 -1
  149. package/es2022/src/plugins/normalState/simpleNormalState/simpleNormalState.component.js +5 -6
  150. package/es2022/src/plugins/normalState/simpleNormalState/simpleNormalState.component.js.map +1 -1
  151. package/es2022/src/plugins/optionsHandler/index.js.map +1 -1
  152. package/es2022/src/plugins/optionsHandler/noOptionsHandler/noOptionsHandler.component.js.map +1 -1
  153. package/es2022/src/plugins/optionsHandler/optionsHandlerBase.js.map +1 -1
  154. package/es2022/src/plugins/optionsHandler/simpleOptionsHandler/simpleOptionsHandler.component.js.map +1 -1
  155. package/es2022/src/plugins/popup/index.js.map +1 -1
  156. package/es2022/src/plugins/popup/simplePopup/simplePopup.component.js +2 -2
  157. package/es2022/src/plugins/popup/simplePopup/simplePopup.component.js.map +1 -1
  158. package/es2022/src/plugins/positioner/commonPositioner/commonPositioner.component.js.map +1 -1
  159. package/es2022/src/plugins/positioner/index.js.map +1 -1
  160. package/es2022/src/plugins/positioner/noPositioner/noPositioner.component.js.map +1 -1
  161. package/es2022/src/plugins/positioner/popoverPositioner/popoverPositioner.component.js.map +1 -1
  162. package/es2022/src/plugins/valueHandler/dynamicValueHandler/dynamicValueHandler.component.js.map +1 -1
  163. package/es2022/src/plugins/valueHandler/index.js.map +1 -1
  164. package/es2022/src/plugins/valueHandler/staticValueHandler/staticValueHandler.component.js.map +1 -1
  165. package/package.json +125 -125
  166. package/src/components/select/select.component.css +5 -5
  167. package/src/interfaces/plugins/normalState/editNormalState.interface.d.ts +4 -0
  168. package/src/interfaces/plugins/normalState/editNormalState.interface.d.ts.map +1 -1
  169. package/src/interfaces/plugins/normalState/simpleNormalState.interface.d.ts +1 -5
  170. package/src/interfaces/plugins/normalState/simpleNormalState.interface.d.ts.map +1 -1
  171. package/src/plugins/liveSearch/editLiveSearch/editLiveSearch.component.html +19 -19
  172. package/src/plugins/normalState/editNormalState/editNormalState.component.d.ts.map +1 -1
  173. package/src/plugins/normalState/editNormalState/editNormalState.component.html +52 -50
  174. package/src/plugins/normalState/simpleNormalState/simpleNormalState.component.d.ts.map +1 -1
  175. package/src/plugins/normalState/simpleNormalState/simpleNormalState.component.html +36 -37
  176. package/src/plugins/popup/simplePopup/simplePopup.component.html +56 -56
  177. package/styles/components/_liveSearch.scss +32 -32
  178. package/styles/components/_normalState.scss +121 -116
  179. package/styles/components/_popup.scss +107 -107
  180. package/styles/components/_select.scss +14 -14
  181. package/styles/core/_defaultTheme.scss +105 -105
  182. package/styles/core/_misc.scss +34 -34
  183. package/styles/core/_mixins.scss +29 -29
  184. package/styles/index.scss +2 -2
  185. package/styles/themes/dark.scss +63 -63
  186. package/styles/themes/light.scss +64 -64
  187. package/version.bak +1 -1
@@ -1,67 +1,67 @@
1
- # Define Routes
2
-
3
- Routes are objects that define which component should render for a specific URL path.
4
-
5
- ## Basic Configuration
6
-
7
- Define routes in a `Routes` array and provide them using `provideRouter` in your `appConfig`.
8
-
9
- ```ts
10
- // app.routes.ts
11
- export const routes: Routes = [
12
- {path: '', component: HomePage},
13
- {path: 'admin', component: AdminPage},
14
- ];
15
-
16
- // app.config.ts
17
- export const appConfig: ApplicationConfig = {
18
- providers: [provideRouter(routes)],
19
- };
20
- ```
21
-
22
- ## URL Paths
23
-
24
- - **Static**: Matches an exact string (e.g., `'admin'`).
25
- - **Route Parameters**: Dynamic segments prefixed with a colon (e.g., `'user/:id'`).
26
- - **Wildcard**: Matches any URL using `**`. Useful for "Not Found" pages. **Always place at the end of the array.**
27
-
28
- ## Matching Strategy
29
-
30
- Angular uses a **first-match wins** strategy. Specific routes must come before less specific ones.
31
-
32
- ## Redirects
33
-
34
- Use `redirectTo` to point one path to another.
35
-
36
- ```ts
37
- { path: 'articles', redirectTo: '/blog' },
38
- { path: 'blog', component: Blog },
39
- ```
40
-
41
- ## Page Titles
42
-
43
- Associate titles with routes for accessibility. Titles can be static or dynamic (via `ResolveFn` or a custom `TitleStrategy`).
44
-
45
- ```ts
46
- { path: 'home', component: Home, title: 'Home Page' }
47
- ```
48
-
49
- ## Route Data and Providers
50
-
51
- - **Static Data**: Attach metadata using the `data` property.
52
- - **Route Providers**: Scope dependencies to a specific route and its children using the `providers` array.
53
-
54
- ## Nested (Child) Routes
55
-
56
- Define sub-views using the `children` property. Parent components must include a `<router-outlet />`.
57
-
58
- ```ts
59
- {
60
- path: 'product/:id',
61
- component: Product,
62
- children: [
63
- { path: 'info', component: ProductInfo },
64
- { path: 'reviews', component: ProductReviews },
65
- ],
66
- }
67
- ```
1
+ # Define Routes
2
+
3
+ Routes are objects that define which component should render for a specific URL path.
4
+
5
+ ## Basic Configuration
6
+
7
+ Define routes in a `Routes` array and provide them using `provideRouter` in your `appConfig`.
8
+
9
+ ```ts
10
+ // app.routes.ts
11
+ export const routes: Routes = [
12
+ {path: '', component: HomePage},
13
+ {path: 'admin', component: AdminPage},
14
+ ];
15
+
16
+ // app.config.ts
17
+ export const appConfig: ApplicationConfig = {
18
+ providers: [provideRouter(routes)],
19
+ };
20
+ ```
21
+
22
+ ## URL Paths
23
+
24
+ - **Static**: Matches an exact string (e.g., `'admin'`).
25
+ - **Route Parameters**: Dynamic segments prefixed with a colon (e.g., `'user/:id'`).
26
+ - **Wildcard**: Matches any URL using `**`. Useful for "Not Found" pages. **Always place at the end of the array.**
27
+
28
+ ## Matching Strategy
29
+
30
+ Angular uses a **first-match wins** strategy. Specific routes must come before less specific ones.
31
+
32
+ ## Redirects
33
+
34
+ Use `redirectTo` to point one path to another.
35
+
36
+ ```ts
37
+ { path: 'articles', redirectTo: '/blog' },
38
+ { path: 'blog', component: Blog },
39
+ ```
40
+
41
+ ## Page Titles
42
+
43
+ Associate titles with routes for accessibility. Titles can be static or dynamic (via `ResolveFn` or a custom `TitleStrategy`).
44
+
45
+ ```ts
46
+ { path: 'home', component: Home, title: 'Home Page' }
47
+ ```
48
+
49
+ ## Route Data and Providers
50
+
51
+ - **Static Data**: Attach metadata using the `data` property.
52
+ - **Route Providers**: Scope dependencies to a specific route and its children using the `providers` array.
53
+
54
+ ## Nested (Child) Routes
55
+
56
+ Define sub-views using the `children` property. Parent components must include a `<router-outlet />`.
57
+
58
+ ```ts
59
+ {
60
+ path: 'product/:id',
61
+ component: Product,
62
+ children: [
63
+ { path: 'info', component: ProductInfo },
64
+ { path: 'reviews', component: ProductReviews },
65
+ ],
66
+ }
67
+ ```
@@ -1,72 +1,72 @@
1
- # Defining Dependency Providers
2
-
3
- Angular offers automatic and manual ways to provide dependencies to its Dependency Injection (DI) system.
4
-
5
- ## Automatic Provision
6
-
7
- The most common way to provide a service is using `providedIn: 'root'` on an `@Injectable()`.
8
-
9
- ### InjectionToken
10
-
11
- Use `InjectionToken` for non-class dependencies (configuration objects, functions, primitives). An `InjectionToken` can also be automatically provided.
12
-
13
- ```ts
14
- import {InjectionToken} from '@angular/core';
15
-
16
- export interface AppConfig {
17
- apiUrl: string;
18
- }
19
-
20
- export const APP_CONFIG = new InjectionToken<AppConfig>('app.config', {
21
- providedIn: 'root',
22
- factory: () => ({apiUrl: 'https://api.example.com'}),
23
- });
24
- ```
25
-
26
- ## Manual Provision
27
-
28
- You use the `providers` array when a service lacks `providedIn`, when you want a new instance for a specific component, or when configuring runtime values.
29
-
30
- ```ts
31
- @Component({
32
- providers: [
33
- // Shorthand for { provide: LocalService, useClass: LocalService }
34
- LocalService,
35
-
36
- // useClass: Swap implementations
37
- {provide: Logger, useClass: BetterLogger},
38
-
39
- // useValue: Provide static values
40
- {provide: API_URL_TOKEN, useValue: 'https://api.example.com'},
41
-
42
- // useFactory: Generate value dynamically
43
- {
44
- provide: ApiClient,
45
- useFactory: (http = inject(HttpClient)) => new ApiClient(http),
46
- },
47
-
48
- // useExisting: Create an alias
49
- {provide: OldLogger, useExisting: NewLogger},
50
-
51
- // multi: Provide multiple values for the same token as an array
52
- {provide: INTERCEPTOR_TOKEN, useClass: AuthInterceptor, multi: true},
53
- ],
54
- })
55
- export class Example {}
56
- ```
57
-
58
- ## Scopes of Providers
59
-
60
- - **Application Bootstrap**: Global singletons. Use for HTTP clients, logging, or app-wide config.
61
- - **Component/Directive**: Isolated instances. Use for component-specific state or forms. Services are destroyed when the component is destroyed.
62
- - **Route**: Feature-specific services loaded only with specific routes.
63
-
64
- ## Library Pattern: `provide*` functions
65
-
66
- Library authors should export functions that return provider arrays to encapsulate configuration:
67
-
68
- ```ts
69
- export function provideAnalytics(config: AnalyticsConfig): Provider[] {
70
- return [{provide: ANALYTICS_CONFIG, useValue: config}, AnalyticsService];
71
- }
72
- ```
1
+ # Defining Dependency Providers
2
+
3
+ Angular offers automatic and manual ways to provide dependencies to its Dependency Injection (DI) system.
4
+
5
+ ## Automatic Provision
6
+
7
+ The most common way to provide a service is using `providedIn: 'root'` on an `@Injectable()`.
8
+
9
+ ### InjectionToken
10
+
11
+ Use `InjectionToken` for non-class dependencies (configuration objects, functions, primitives). An `InjectionToken` can also be automatically provided.
12
+
13
+ ```ts
14
+ import {InjectionToken} from '@angular/core';
15
+
16
+ export interface AppConfig {
17
+ apiUrl: string;
18
+ }
19
+
20
+ export const APP_CONFIG = new InjectionToken<AppConfig>('app.config', {
21
+ providedIn: 'root',
22
+ factory: () => ({apiUrl: 'https://api.example.com'}),
23
+ });
24
+ ```
25
+
26
+ ## Manual Provision
27
+
28
+ You use the `providers` array when a service lacks `providedIn`, when you want a new instance for a specific component, or when configuring runtime values.
29
+
30
+ ```ts
31
+ @Component({
32
+ providers: [
33
+ // Shorthand for { provide: LocalService, useClass: LocalService }
34
+ LocalService,
35
+
36
+ // useClass: Swap implementations
37
+ {provide: Logger, useClass: BetterLogger},
38
+
39
+ // useValue: Provide static values
40
+ {provide: API_URL_TOKEN, useValue: 'https://api.example.com'},
41
+
42
+ // useFactory: Generate value dynamically
43
+ {
44
+ provide: ApiClient,
45
+ useFactory: (http = inject(HttpClient)) => new ApiClient(http),
46
+ },
47
+
48
+ // useExisting: Create an alias
49
+ {provide: OldLogger, useExisting: NewLogger},
50
+
51
+ // multi: Provide multiple values for the same token as an array
52
+ {provide: INTERCEPTOR_TOKEN, useClass: AuthInterceptor, multi: true},
53
+ ],
54
+ })
55
+ export class Example {}
56
+ ```
57
+
58
+ ## Scopes of Providers
59
+
60
+ - **Application Bootstrap**: Global singletons. Use for HTTP clients, logging, or app-wide config.
61
+ - **Component/Directive**: Isolated instances. Use for component-specific state or forms. Services are destroyed when the component is destroyed.
62
+ - **Route**: Feature-specific services loaded only with specific routes.
63
+
64
+ ## Library Pattern: `provide*` functions
65
+
66
+ Library authors should export functions that return provider arrays to encapsulate configuration:
67
+
68
+ ```ts
69
+ export function provideAnalytics(config: AnalyticsConfig): Provider[] {
70
+ return [{provide: ANALYTICS_CONFIG, useValue: config}, AnalyticsService];
71
+ }
72
+ ```
@@ -1,120 +1,120 @@
1
- # Dependency Injection (DI) Fundamentals
2
-
3
- Dependency Injection (DI) is a design pattern used to organize and share code across an application by allowing you to "inject" features into different parts. This improves code maintainability, scalability, and testability.
4
-
5
- ## How DI Works in Angular
6
-
7
- There are two primary ways code interacts with Angular's DI system:
8
-
9
- 1. **Providing**: Making values (objects, functions, primitives) available to the DI system.
10
- 2. **Injecting**: Asking the DI system for those values.
11
-
12
- Angular components, directives, and services automatically participate in DI.
13
-
14
- ## Services
15
-
16
- A **service** is the most common way to share data and functionality across an application. It is a TypeScript class decorated with `@Injectable()`.
17
-
18
- ### Creating a Service
19
-
20
- Use the `providedIn: 'root'` option in the `@Injectable` decorator to make the service a singleton available throughout the entire application. This is the recommended approach for most services.
21
-
22
- ```ts
23
- import {Injectable} from '@angular/core';
24
-
25
- @Injectable({
26
- providedIn: 'root', // Makes this a singleton available everywhere
27
- })
28
- export class AnalyticsLogger {
29
- trackEvent(category: string, value: string) {
30
- console.log('Analytics event logged:', {category, value});
31
- }
32
- }
33
- ```
34
-
35
- Common uses for services include:
36
-
37
- - Data clients (API calls)
38
- - State management
39
- - Authentication and authorization
40
- - Logging and error handling
41
- - Utility functions
42
-
43
- ## Injecting Dependencies
44
-
45
- Use Angular's `inject()` function to request dependencies.
46
-
47
- ### The `inject()` Function
48
-
49
- You can use the `inject()` function to get an instance of a service (or any other provided token).
50
-
51
- ```ts
52
- import {Component, inject} from '@angular/core';
53
- import {Router} from '@angular/router';
54
- import {AnalyticsLogger} from './analytics-logger.service';
55
-
56
- @Component({
57
- selector: 'app-navbar',
58
- template: `<a href="#" (click)="navigateToDetail($event)">Detail Page</a>`,
59
- })
60
- export class Navbar {
61
- // Injecting dependencies using class field initializers
62
- private router = inject(Router);
63
- private analytics = inject(AnalyticsLogger);
64
-
65
- navigateToDetail(event: Event) {
66
- event.preventDefault();
67
- this.analytics.trackEvent('navigation', '/details');
68
- this.router.navigate(['/details']);
69
- }
70
- }
71
- ```
72
-
73
- ### Where can `inject()` be used? (Injection Context)
74
-
75
- You can call `inject()` in an **injection context**. The most common injection contexts are during the construction of a component, directive, or service.
76
-
77
- Valid places to call `inject()`:
78
-
79
- 1. **Class field initializers** (Recommended)
80
- 2. **Constructor body**
81
- 3. **Route guards and resolvers** (which are executed in an injection context)
82
- 4. **Factory functions** used in providers
83
-
84
- ```typescript
85
- import {Component, Directive, Injectable, inject, ElementRef} from '@angular/core';
86
- import {HttpClient} from '@angular/common/http';
87
-
88
- // 1. In a Component (Field Initializer & Constructor)
89
- @Component({
90
- /*...*/
91
- })
92
- export class Example {
93
- private service1 = inject(MyService); // ✅ Field initializer
94
-
95
- private service2: MyService;
96
- constructor() {
97
- this.service2 = inject(MyService); // ✅ Constructor body
98
- }
99
- }
100
-
101
- // 2. In a Directive
102
- @Directive({
103
- /*...*/
104
- })
105
- export class MyDirective {
106
- private element = inject(ElementRef); // ✅ Field initializer
107
- }
108
-
109
- // 3. In a Service
110
- @Injectable({providedIn: 'root'})
111
- export class MyService {
112
- private http = inject(HttpClient); // ✅ Field initializer
113
- }
114
-
115
- // 4. In a Route Guard (Functional)
116
- export const authGuard = () => {
117
- const auth = inject(AuthService); // ✅ Route Guard
118
- return auth.isAuthenticated();
119
- };
120
- ```
1
+ # Dependency Injection (DI) Fundamentals
2
+
3
+ Dependency Injection (DI) is a design pattern used to organize and share code across an application by allowing you to "inject" features into different parts. This improves code maintainability, scalability, and testability.
4
+
5
+ ## How DI Works in Angular
6
+
7
+ There are two primary ways code interacts with Angular's DI system:
8
+
9
+ 1. **Providing**: Making values (objects, functions, primitives) available to the DI system.
10
+ 2. **Injecting**: Asking the DI system for those values.
11
+
12
+ Angular components, directives, and services automatically participate in DI.
13
+
14
+ ## Services
15
+
16
+ A **service** is the most common way to share data and functionality across an application. It is a TypeScript class decorated with `@Injectable()`.
17
+
18
+ ### Creating a Service
19
+
20
+ Use the `providedIn: 'root'` option in the `@Injectable` decorator to make the service a singleton available throughout the entire application. This is the recommended approach for most services.
21
+
22
+ ```ts
23
+ import {Injectable} from '@angular/core';
24
+
25
+ @Injectable({
26
+ providedIn: 'root', // Makes this a singleton available everywhere
27
+ })
28
+ export class AnalyticsLogger {
29
+ trackEvent(category: string, value: string) {
30
+ console.log('Analytics event logged:', {category, value});
31
+ }
32
+ }
33
+ ```
34
+
35
+ Common uses for services include:
36
+
37
+ - Data clients (API calls)
38
+ - State management
39
+ - Authentication and authorization
40
+ - Logging and error handling
41
+ - Utility functions
42
+
43
+ ## Injecting Dependencies
44
+
45
+ Use Angular's `inject()` function to request dependencies.
46
+
47
+ ### The `inject()` Function
48
+
49
+ You can use the `inject()` function to get an instance of a service (or any other provided token).
50
+
51
+ ```ts
52
+ import {Component, inject} from '@angular/core';
53
+ import {Router} from '@angular/router';
54
+ import {AnalyticsLogger} from './analytics-logger.service';
55
+
56
+ @Component({
57
+ selector: 'app-navbar',
58
+ template: `<a href="#" (click)="navigateToDetail($event)">Detail Page</a>`,
59
+ })
60
+ export class Navbar {
61
+ // Injecting dependencies using class field initializers
62
+ private router = inject(Router);
63
+ private analytics = inject(AnalyticsLogger);
64
+
65
+ navigateToDetail(event: Event) {
66
+ event.preventDefault();
67
+ this.analytics.trackEvent('navigation', '/details');
68
+ this.router.navigate(['/details']);
69
+ }
70
+ }
71
+ ```
72
+
73
+ ### Where can `inject()` be used? (Injection Context)
74
+
75
+ You can call `inject()` in an **injection context**. The most common injection contexts are during the construction of a component, directive, or service.
76
+
77
+ Valid places to call `inject()`:
78
+
79
+ 1. **Class field initializers** (Recommended)
80
+ 2. **Constructor body**
81
+ 3. **Route guards and resolvers** (which are executed in an injection context)
82
+ 4. **Factory functions** used in providers
83
+
84
+ ```typescript
85
+ import {Component, Directive, Injectable, inject, ElementRef} from '@angular/core';
86
+ import {HttpClient} from '@angular/common/http';
87
+
88
+ // 1. In a Component (Field Initializer & Constructor)
89
+ @Component({
90
+ /*...*/
91
+ })
92
+ export class Example {
93
+ private service1 = inject(MyService); // ✅ Field initializer
94
+
95
+ private service2: MyService;
96
+ constructor() {
97
+ this.service2 = inject(MyService); // ✅ Constructor body
98
+ }
99
+ }
100
+
101
+ // 2. In a Directive
102
+ @Directive({
103
+ /*...*/
104
+ })
105
+ export class MyDirective {
106
+ private element = inject(ElementRef); // ✅ Field initializer
107
+ }
108
+
109
+ // 3. In a Service
110
+ @Injectable({providedIn: 'root'})
111
+ export class MyService {
112
+ private http = inject(HttpClient); // ✅ Field initializer
113
+ }
114
+
115
+ // 4. In a Route Guard (Functional)
116
+ export const authGuard = () => {
117
+ const auth = inject(AuthService); // ✅ Route Guard
118
+ return auth.isAuthenticated();
119
+ };
120
+ ```
@@ -1,66 +1,66 @@
1
- # End-to-End (E2E) Testing
2
-
3
- This project uses [Cypress](https://www.cypress.io/) for end-to-end (E2E) testing, which simulates real user interactions in a browser. The E2E tests are located primarily within the `devtools/` package.
4
-
5
- ## Running E2E Tests
6
-
7
- The primary way to run E2E tests is through the `pnpm` script defined in the root `package.json`.
8
-
9
- 1. **Build DevTools:** The E2E tests run against a built version of the devtools extension. You must build it first:
10
-
11
- ```shell
12
- pnpm -F ng-devtools-mcp build:dev
13
- ```
14
-
15
- 2. **Run Cypress:** Use the `cy:open` or `cy:run` script:
16
- - To open the interactive Cypress Test Runner:
17
- ```shell
18
- pnpm -F ng-devtools-mcp cy:open
19
- ```
20
- - To run the tests headlessly in the terminal (ideal for CI):
21
- ```shell
22
- pnpm -F ng-devtools-mcp cy:run
23
- ```
24
-
25
- ## Test Structure
26
-
27
- - **Configuration:** The main Cypress configuration is located at `devtools/cypress.json`.
28
- - **Specs:** Test files (specs) are located in `devtools/cypress/integration/`.
29
- - **Custom Commands:** Reusable custom commands and actions are defined in `devtools/cypress/support/`.
30
-
31
- ### Example E2E Test Snippet
32
-
33
- A typical test might look like this:
34
-
35
- ```typescript
36
- // in devtools/cypress/integration/profiler.spec.ts
37
-
38
- describe('Profiler', () => {
39
- beforeEach(() => {
40
- cy.visit('/?e2e-app');
41
- cy.wait(1000);
42
- cy.get('ng-devtools-tabs').find('a').contains('Profiler').click();
43
- });
44
-
45
- it('should record and display profiling data', () => {
46
- // Find the record button and click it
47
- cy.get('button[aria-label="start-recording-button"]').click();
48
-
49
- // Interact with the test application to generate profiling data
50
- cy.get('body').find('#cards button').first().click();
51
- cy.wait(500);
52
-
53
- // Stop recording
54
- cy.get('button[aria-label="stop-recording-button"]').click();
55
-
56
- // Assert that the flame graph is now visible
57
- cy.get('ng-devtools-recording-timeline').find('canvas').should('be.visible');
58
- });
59
- });
60
- ```
61
-
62
- ### Best Practices
63
-
64
- - **Use `data-` attributes:** Whenever possible, use `data-cy` or similar attributes for selecting elements to make tests more resilient to CSS or structural changes.
65
- - **Custom Commands:** Encapsulate common sequences of actions into custom commands in the `support` directory to keep tests clean and readable.
66
- - **Wait for Application State:** Use `cy.wait()` for arbitrary waits sparingly. Prefer to wait for specific UI elements to appear or for network requests to complete to avoid flaky tests.
1
+ # End-to-End (E2E) Testing
2
+
3
+ This project uses [Cypress](https://www.cypress.io/) for end-to-end (E2E) testing, which simulates real user interactions in a browser. The E2E tests are located primarily within the `devtools/` package.
4
+
5
+ ## Running E2E Tests
6
+
7
+ The primary way to run E2E tests is through the `pnpm` script defined in the root `package.json`.
8
+
9
+ 1. **Build DevTools:** The E2E tests run against a built version of the devtools extension. You must build it first:
10
+
11
+ ```shell
12
+ pnpm -F ng-devtools-mcp build:dev
13
+ ```
14
+
15
+ 2. **Run Cypress:** Use the `cy:open` or `cy:run` script:
16
+ - To open the interactive Cypress Test Runner:
17
+ ```shell
18
+ pnpm -F ng-devtools-mcp cy:open
19
+ ```
20
+ - To run the tests headlessly in the terminal (ideal for CI):
21
+ ```shell
22
+ pnpm -F ng-devtools-mcp cy:run
23
+ ```
24
+
25
+ ## Test Structure
26
+
27
+ - **Configuration:** The main Cypress configuration is located at `devtools/cypress.json`.
28
+ - **Specs:** Test files (specs) are located in `devtools/cypress/integration/`.
29
+ - **Custom Commands:** Reusable custom commands and actions are defined in `devtools/cypress/support/`.
30
+
31
+ ### Example E2E Test Snippet
32
+
33
+ A typical test might look like this:
34
+
35
+ ```typescript
36
+ // in devtools/cypress/integration/profiler.spec.ts
37
+
38
+ describe('Profiler', () => {
39
+ beforeEach(() => {
40
+ cy.visit('/?e2e-app');
41
+ cy.wait(1000);
42
+ cy.get('ng-devtools-tabs').find('a').contains('Profiler').click();
43
+ });
44
+
45
+ it('should record and display profiling data', () => {
46
+ // Find the record button and click it
47
+ cy.get('button[aria-label="start-recording-button"]').click();
48
+
49
+ // Interact with the test application to generate profiling data
50
+ cy.get('body').find('#cards button').first().click();
51
+ cy.wait(500);
52
+
53
+ // Stop recording
54
+ cy.get('button[aria-label="stop-recording-button"]').click();
55
+
56
+ // Assert that the flame graph is now visible
57
+ cy.get('ng-devtools-recording-timeline').find('canvas').should('be.visible');
58
+ });
59
+ });
60
+ ```
61
+
62
+ ### Best Practices
63
+
64
+ - **Use `data-` attributes:** Whenever possible, use `data-cy` or similar attributes for selecting elements to make tests more resilient to CSS or structural changes.
65
+ - **Custom Commands:** Encapsulate common sequences of actions into custom commands in the `support` directory to keep tests clean and readable.
66
+ - **Wait for Application State:** Use `cy.wait()` for arbitrary waits sparingly. Prefer to wait for specific UI elements to appear or for network requests to complete to avoid flaky tests.