Skip to content

Commit 44af03d

Browse files
committed
docs: modernize creating-services reference with signal state and asReadonly
1 parent 51cb07e commit 44af03d

1 file changed

Lines changed: 17 additions & 21 deletions

File tree

‎skills/dev-skills/angular-developer/references/creating-services.md‎

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,20 @@ You can generate a service using the Angular CLI:
1010
ng generate service my-data
1111
```
1212

13-
Or you can manually create a TypeScript class and decorate it with `@Service()`.
13+
Or you can manually create a TypeScript class and decorate it with `@Service()`. For reactive state management, store data in a private `signal()` and expose it publicly via `.asReadonly()`:
1414

1515
```ts
16-
import {Service} from '@angular/core';
16+
import {Service, signal} from '@angular/core';
1717

1818
@Service()
1919
export class BasicDataStore {
20-
private data: string[] = [];
20+
private readonly _data = signal<string[]>([]);
2121

22-
addData(item: string): void {
23-
this.data.push(item);
24-
}
22+
// Expose state as a read-only signal to prevent direct external mutation
23+
readonly data = this._data.asReadonly();
2524

26-
getData(): string[] {
27-
return [...this.data];
25+
addData(item: string): void {
26+
this._data.update((items) => [...items, item]);
2827
}
2928
}
3029
```
@@ -39,7 +38,7 @@ Using `@Service` is the recommended approach for most services. It tells Angular
3938

4039
#### The `autoProvided` option
4140

42-
If you don't want to create a singleton of your service, you can set `@Service({autoProvided: false})` and declare the service a `providers` array.
41+
If you don't want to create a singleton of your service, you can set `@Service({autoProvided: false})` and declare the service in a `providers` array.
4342

4443
## Injecting a Service
4544

@@ -55,36 +54,33 @@ import {BasicDataStore} from './basic-data-store.service';
5554
selector: 'app-example',
5655
template: `
5756
<div>
58-
<p>Data items: {{ dataStore.getData().length }}</p>
57+
<p>Data items: {{ dataStore.data().length }}</p>
5958
<button (click)="dataStore.addData('New Item')">Add Item</button>
6059
</div>
6160
`,
6261
})
6362
export class Example {
6463
// Inject the service as a class field
65-
dataStore = inject(BasicDataStore);
64+
readonly dataStore = inject(BasicDataStore);
6665
}
6766
```
6867

6968
### Injecting into Another Service
7069

71-
Services can inject other services in the exact same way.
70+
Services can inject other services in the exact same way. Use `computed()` to derive values from injected services reactively:
7271

7372
```ts
74-
import {Injectable, inject} from '@angular/core';
73+
import {Service, computed, inject, signal} from '@angular/core';
7574
import {AdvancedDataStore} from './advanced-data-store.service';
7675

7776
@Service()
78-
export class BasicDataStore {
77+
export class CombinedDataStore {
7978
// Injecting another service
80-
private advancedDataStore = inject(AdvancedDataStore);
81-
82-
private data: string[] = [];
79+
private readonly advancedDataStore = inject(AdvancedDataStore);
80+
private readonly _data = signal<string[]>([]);
8381

84-
getData(): string[] {
85-
// Combine data from this service and the injected service
86-
return [...this.data, ...this.advancedDataStore.getData()];
87-
}
82+
// Combine reactive state from this service and the injected service
83+
readonly allData = computed(() => [...this._data(), ...this.advancedDataStore.data()]);
8884
}
8985
```
9086

0 commit comments

Comments
 (0)