1643088000
「大いなる力には、大いなる力には大いなる力があります」—あなたは誰を知っていますか。それは本当です!Angular Formsは強力であるだけでなく、コントローラーに大きな混乱を引き起こします。FormBuilder、FormGroup、FormControl、ロジックの保存、ロジックの更新—ほとんど狂気。今日は、フォームを管理し、正気をもたらす方法を紹介します。
サービスを入力してください—それらは注射可能であり、必要なときに提供されます。それなら、フォームを管理するためにサービスを使用してみませんか?それでは始めましょう。
まず、インターフェースを作成する必要があります。このデモでActor
は、2つのインターフェイスを作成します。これは最終的なエンティティでありActorCreateInput
、フォーム入力の形状です。
ルートに挿入されない、つまり{ providedIn: 'root' }
デコレータに渡されないActorCreateFormServiceを作成します。
これまでのところ、すべてが自明です。この段階では、サービスはFormGroupを作成し、それをform
クラスプロパティに割り当てる以外は何もしません。フォームの値と有効性を取得するための便利なメソッドをいくつか追加しました。
アクターを保存または更新するには、HTTPサービスに接続する必要があります。その仕事をするActorApiServiceがあるとしましょう。だからそれを注入します:
constructor(
private fb: FormBuilder,
private actorApiService: ActorApiService,
) {}
次に、アクターを作成および更新するためのいくつかのメソッドを記述しましょう。
データベースからアクターをロードしてフォームに入力するには、最後の1つのメソッドが必要です。これは、アクターを編集する必要がある場合に便利です。
コンポーネントでどのように使用できるかを見てみましょう。で提供しなかったためroot
、正しいスコープ(通常はコンポーネント)で提供する必要があります。
コントローラがどれほどきれいであるかに注目してください。さらに、他の場所でも同じフォームサービスを使用できます。
まだ終わっていません。よく見ると、フォームサービスには、他のフォームにも使用できる再利用可能な部分がいくつかあります。たとえば、MovieCreateFormServiceです。それでは、フォームクラスをさらに一歩進めて、抽象化してみましょうAbstractFormService
。デコレータを含める必要がなくなりました@Injectable()
:(簡潔にするために一部のコードは省略されています)。
次に、MovieCreateFormServiceを作成して拡張します。
これで、フォームを実現するために4つのメソッドをオーバーライドする必要があります。フォームの送信時に、保存、更新、リセットを自動的に処理します。MovieCreateFormService
これで、以前と同じように使用できActorCreateFormService
ます。
このアプローチについてどう思いますか?このパターンにより、アプリケーション全体で多くのLOC(コード行)が節約されると思います。しかし、潜在的な問題や改善についての考えを共有してください。
読んでくれてありがとう!
import { FormBuilder, FormControl, FormGroup } from '@angular/forms'
import { Observable, throwError } from 'rxjs'
export abstract class AbstractFormService<T, InputT extends { id?: string }> {
form: FormGroup
constructor(protected fb: FormBuilder) {
this.form = this.buildForm()
}
get valid(): boolean {
if (this.form.untouched) return false
return this.form.valid
}
getFormValue(): InputT {
return this.form.value
}
setFormValue(dto: InputT | null): void {
if (!dto) {
this.form.reset()
return
}
this.form.reset(dto)
if (dto.id) {
const control = new FormControl(dto.id)
this.form.addControl('id', control)
}
}
abstract buildForm(): FormGroup
abstract loadFromApiAndFillForm$(id: string): Observable<T>
save$(): Observable<T> {
if (this.form.invalid) return throwError(() => new Error('Invalid form'))
const id = this.form.get('id')?.value ?? null
return id ? this.update$(id) : this.create$()
}
protected abstract create$(): Observable<T>
protected abstract update$(id: string): Observable<T>
}
@Injectable()
export class MovieCreateFormService extends AbstractFormService<Movie, MovieCreateInput> {
constructor(protected override fb: FormBuilder, private movieService: MovieService) {
super(fb)
}
buildForm(): FormGroup {
return this.fb.group({
name: ['', Validators.required],
releaseYear: '',
genre: '',
})
}
loadFromApiAndFillForm$(id: string): Observable<Movie> {
return this.movieService
.findById(id)
.pipe(tap((data) => this.setFormValue(data)))
}
protected create$(): Observable<Movie> {
return this.movieService
.create(this.getFormValue())
.pipe(tap(() => this.form.reset()))
}
protected update$(id: string): Observable<Movie> {
return this.movieService
.update(id, this.getFormValue())
.pipe(tap(() => this.form.reset()))
}
}
リンク:https ://javascript.plainenglish.io/a-better-way-to-use-angular-forms-cd22a5a0488a
1643088000
「大いなる力には、大いなる力には大いなる力があります」—あなたは誰を知っていますか。それは本当です!Angular Formsは強力であるだけでなく、コントローラーに大きな混乱を引き起こします。FormBuilder、FormGroup、FormControl、ロジックの保存、ロジックの更新—ほとんど狂気。今日は、フォームを管理し、正気をもたらす方法を紹介します。
サービスを入力してください—それらは注射可能であり、必要なときに提供されます。それなら、フォームを管理するためにサービスを使用してみませんか?それでは始めましょう。
まず、インターフェースを作成する必要があります。このデモでActor
は、2つのインターフェイスを作成します。これは最終的なエンティティでありActorCreateInput
、フォーム入力の形状です。
ルートに挿入されない、つまり{ providedIn: 'root' }
デコレータに渡されないActorCreateFormServiceを作成します。
これまでのところ、すべてが自明です。この段階では、サービスはFormGroupを作成し、それをform
クラスプロパティに割り当てる以外は何もしません。フォームの値と有効性を取得するための便利なメソッドをいくつか追加しました。
アクターを保存または更新するには、HTTPサービスに接続する必要があります。その仕事をするActorApiServiceがあるとしましょう。だからそれを注入します:
constructor(
private fb: FormBuilder,
private actorApiService: ActorApiService,
) {}
次に、アクターを作成および更新するためのいくつかのメソッドを記述しましょう。
データベースからアクターをロードしてフォームに入力するには、最後の1つのメソッドが必要です。これは、アクターを編集する必要がある場合に便利です。
コンポーネントでどのように使用できるかを見てみましょう。で提供しなかったためroot
、正しいスコープ(通常はコンポーネント)で提供する必要があります。
コントローラがどれほどきれいであるかに注目してください。さらに、他の場所でも同じフォームサービスを使用できます。
まだ終わっていません。よく見ると、フォームサービスには、他のフォームにも使用できる再利用可能な部分がいくつかあります。たとえば、MovieCreateFormServiceです。それでは、フォームクラスをさらに一歩進めて、抽象化してみましょうAbstractFormService
。デコレータを含める必要がなくなりました@Injectable()
:(簡潔にするために一部のコードは省略されています)。
次に、MovieCreateFormServiceを作成して拡張します。
これで、フォームを実現するために4つのメソッドをオーバーライドする必要があります。フォームの送信時に、保存、更新、リセットを自動的に処理します。MovieCreateFormService
これで、以前と同じように使用できActorCreateFormService
ます。
このアプローチについてどう思いますか?このパターンにより、アプリケーション全体で多くのLOC(コード行)が節約されると思います。しかし、潜在的な問題や改善についての考えを共有してください。
読んでくれてありがとう!
import { FormBuilder, FormControl, FormGroup } from '@angular/forms'
import { Observable, throwError } from 'rxjs'
export abstract class AbstractFormService<T, InputT extends { id?: string }> {
form: FormGroup
constructor(protected fb: FormBuilder) {
this.form = this.buildForm()
}
get valid(): boolean {
if (this.form.untouched) return false
return this.form.valid
}
getFormValue(): InputT {
return this.form.value
}
setFormValue(dto: InputT | null): void {
if (!dto) {
this.form.reset()
return
}
this.form.reset(dto)
if (dto.id) {
const control = new FormControl(dto.id)
this.form.addControl('id', control)
}
}
abstract buildForm(): FormGroup
abstract loadFromApiAndFillForm$(id: string): Observable<T>
save$(): Observable<T> {
if (this.form.invalid) return throwError(() => new Error('Invalid form'))
const id = this.form.get('id')?.value ?? null
return id ? this.update$(id) : this.create$()
}
protected abstract create$(): Observable<T>
protected abstract update$(id: string): Observable<T>
}
@Injectable()
export class MovieCreateFormService extends AbstractFormService<Movie, MovieCreateInput> {
constructor(protected override fb: FormBuilder, private movieService: MovieService) {
super(fb)
}
buildForm(): FormGroup {
return this.fb.group({
name: ['', Validators.required],
releaseYear: '',
genre: '',
})
}
loadFromApiAndFillForm$(id: string): Observable<Movie> {
return this.movieService
.findById(id)
.pipe(tap((data) => this.setFormValue(data)))
}
protected create$(): Observable<Movie> {
return this.movieService
.create(this.getFormValue())
.pipe(tap(() => this.form.reset()))
}
protected update$(id: string): Observable<Movie> {
return this.movieService
.update(id, this.getFormValue())
.pipe(tap(() => this.form.reset()))
}
}
リンク:https ://javascript.plainenglish.io/a-better-way-to-use-angular-forms-cd22a5a0488a