Angular 覚え書きです。 今回は 前回作成したコードに追加して DI(Dependency Injection) するための サービス FixtextService を追加します。
プロジェクトルートにて:
$ npx ng generate service fixtext
雛形のコードが作成されるのでそれ src/app/fixtext.service.ts を修正する。
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class FixtextService {
constructor() { }
toReverseText(text: string): string {
return text.split('').reverse().join('');
}
}
受け取った文字列をひっくり返した文字列を返す toReverseText 関数を追加しました。
toReverseText(text: string): string {
return text.split('').reverse().join('');
}
テキストフィールドに入力された文字列を受け取って show する段階で文字列をひっくり返すことにします。 したがって ContainerComponent の show 関数にこの処理を入れます。
src/app/container/container.component.ts :
import { Component } from '@angular/core';
import { InputComponent } from '../input/input.component';
import { ShowComponent } from '../show/show.component';
import { FixtextService } from '../fixtext.service';
@Component({
selector: 'app-container',
imports: [InputComponent, ShowComponent],
templateUrl: './container.component.html',
styleUrl: './container.component.css'
})
export class ContainerComponent {
textfieldValue: string = '';
show(textfieldValue: string): void {
const service : FixtextService= new FixtextService();
this.textfieldValue = service.toReverseText(textfieldValue);
}
}
元の show 関数は次のように...
show(textfieldValue: string): void {
this.textfieldValue = textfieldValue;
}
単に受け取った textfieldValue を this.textfieldValue にセットしていました。 これを次のように修正しました。
show(textfieldValue: string): void {
const service : FixtextService = new FixtextService();
this.textfieldValue = service.toReverseText(textfieldValue);
}
もちろん、 FixtextService を使えるように 先頭で それを import しています。
import { FixtextService } from '../fixtext.service';
src/app/container/container.component.ts を DI ありに修正します。
import { Component } from '@angular/core';
import { InputComponent } from '../input/input.component';
import { ShowComponent } from '../show/show.component';
import { FixtextService } from '../fixtext.service';
@Component({
selector: 'app-container',
imports: [InputComponent, ShowComponent],
templateUrl: './container.component.html',
styleUrl: './container.component.css'
})
export class ContainerComponent {
textfieldValue: string = '';
constructor(private service: FixtextService){}
show(textfieldValue: string): void {
this.textfieldValue = this.service.toReverseText(textfieldValue);
}
}
変更点は、まず ContainerComponent クラスに constructor を追加してここで FixtextService を DI します。
constructor(private service: FixtextService){}
その後、これを show 関数で使うだけですが、修正前とは異なり this.service とする必要があります。
show(textfieldValue: string): void {
this.textfieldValue = this.service.toReverseText(textfieldValue);
}
constructor で DI する代わりに inject 関数を使って DI することもできます。
その場合の src/app/container/container.component.ts は次にようになります。
import { Component } from '@angular/core';
import { InputComponent } from '../input/input.component';
import { ShowComponent } from '../show/show.component';
import { FixtextService } from '../fixtext.service';
import { inject } from '@angular/core';
@Component({
selector: 'app-container',
imports: [InputComponent, ShowComponent],
templateUrl: './container.component.html',
styleUrl: './container.component.css'
})
export class ContainerComponent {
textfieldValue: string = '';
service: FixtextService = inject(FixtextService);
show(textfieldValue: string): void {
this.textfieldValue = this.service.toReverseText(textfieldValue);
}
}
まず inject 関数を import します。
import { inject } from '@angular/core';
あとは、この inject を使ってサービスインスタンスを作成します。
service: FixtextService = inject(FixtextService);
あとは show 関数でこのサービスを使うだけです。
show(textfieldValue: string): void {
this.textfieldValue = this.service.toReverseText(textfieldValue);
}
次のように書くこともできます。
show(textfieldValue: string): void { const service = inject(FixtextService); this.textfieldValue = service.toReverseText(textfieldValue); }
この場合 show するたびに FixtextService を inject されるのでちょっと気持悪いかもしれません。 もし、このサービスがめったに使われないのであればこれが適当な実装方法になる可能性はあります。
今回の例のように一カ所でしか使わないサービスを DI する意味は薄い。 複数のコンポーネントでひとつのサービスを使う場合に、それぞれで new FixtextService() するのではなく DI するという使い方になる。 とくにサービスが何か状態とか値を保持するものであったり、データベースと接続するものである場合、 そのサービスがアプリ内で唯一のインスタンスであってほしい場合がある。 もし方々で new サービス してしまうと意図しない作動になるのは目に見えている。 そんなときに DI を使うのはとても自然。