Skip to content

Commit c88305d

Browse files
kapunahelewongmhevery
authored andcommitted
docs: add Injectable migration docs (angular#32581)
PR Close angular#32581
1 parent 64fd0d6 commit c88305d

3 files changed

Lines changed: 96 additions & 2 deletions

File tree

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,8 @@ testing/** @angular/fw-test
845845
/aio/content/guide/migration-renderer.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
846846
/aio/content/guide/migration-undecorated-classes.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
847847
/aio/content/guide/migration-dynamic-flag.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
848+
/aio/content/guide/migration-injectable.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
849+
848850

849851

850852
# ================================================

aio/content/guide/deprecations.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,10 +361,16 @@ See the [dedicated migration guide for Renderer](guide/migration-renderer).
361361

362362
{@a undecorated-classes}
363363
### Migrating undecorated classes
364-
See the [dedicated migration guide for undecorated classes](guide/migration-undecorated-classes).
364+
365+
See the [dedicated migration guide for undecorated classes](guide/migration-undecorated-classes).
366+
367+
{@a injectable}
368+
### Adding missing `@Injectable()` decorators
369+
370+
See the [dedicated migration guide for adding missing `@Injectable` decorators](guide/migration-injectable).
365371

366372
{@a flag-migration}
367-
### Dynamic queries flag migration
373+
### Migrating dynamic queries
368374

369375
See the [dedicated migration guide for dynamic queries](guide/migration-dynamic-flag).
370376

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Migration to Add Missing `@Injectable()` Decorators
2+
3+
## What does this schematic do?
4+
5+
This schematic adds an `@Injectable()` decorator to a class
6+
if the class has been added as a provider anywhere in the application.
7+
8+
An example diff might look like the following:
9+
10+
**Before:**
11+
12+
```ts
13+
export class TypeCase {...}
14+
```
15+
16+
**After:**
17+
18+
```ts
19+
@Injectable()
20+
export class TypeCase {...}
21+
```
22+
23+
24+
There are a few cases where the decorator won't be added. For example:
25+
26+
- It already has another decorator such as `@Component()`, `@Directive()` or `@Pipe()`. These decorators already cause the compiler to generate the necessary information.
27+
- The provider definition has `useValue`, `useFactory`, or `useExisting`. In
28+
these cases, the framework doesn't need the `@Injectable()` decorator to create the class because
29+
because it can just use the value,
30+
factory function, or existing instance that was provided.
31+
32+
For example, for the following module definition, the schematic will check
33+
`TypeCase`, `ProvideCase`, `ExistingClass`, and `SomeClass` to ensure they
34+
are marked with the `@Injectable()` decorator and add one if not.
35+
36+
37+
```ts
38+
@NgModule({
39+
providers: [
40+
// TypeCase needs @Injectable()
41+
TypeCase,
42+
// ProvideCase needs @Injectable()
43+
{provide: ProvideCase},
44+
// No @Injectable() needed because the value will be used
45+
{provide: ValueCase, useValue: 0},
46+
// No @Injectable() needed because factory will be used
47+
{provide: FactoryCase, useFactory: ()=> null},
48+
// ExistingClass needs @Injectable()
49+
{provide: ExistingToken, useExisting: ExistingClass},
50+
// SomeClass needs @Injectable()
51+
{provide: ClassToken, useClass: SomeClass},
52+
// No @Injectable() needed because it has a @Pipe() decorator
53+
PipeCase,
54+
55+
]
56+
})
57+
58+
```
59+
60+
61+
## Why is this migration necessary?
62+
63+
In our docs, we've always recommended adding `@Injectable()`
64+
decorators to any class that is provided or injected in your application.
65+
However, older versions of Angular did allow injection of a class
66+
without the decorator in certain cases, such as AOT mode.
67+
This means if you accidentally omitted the decorator, your application
68+
may have continued to work despite missing `@Injectable()` decorators in some places.
69+
This is problematic for future versions of Angular. Eventually, we plan
70+
to strictly require the decorator because doing so enables further
71+
optimization of both the compiler and the runtime. This schematic
72+
adds any `@Injectable()` decorators that may be missing to future-proof your app.
73+
74+
75+
76+
## When should I be adding `@Injectable()` decorators to classes?
77+
78+
Any class that is provided or injected somewhere must have an `@Injectable()` decorator. The decorator is necessary for the framework to properly create an instance of that class through DI.
79+
80+
However, as noted above, classes that already have another class decorator like `@Pipe` do not need both decorators. The existing class decorator will cause the compiler to generate the proper information.
81+
82+
83+
## Should I update my library?
84+
85+
Yes, if your library has any tokens that are meant to be injected, they should be updated with the `@Injectable()` decorator. In a future version of Angular, a missing `@Injectable()` decorator will always throw an error.
86+

0 commit comments

Comments
 (0)