Angular 响应式表单 - 从数组中读取/设置值
Angular Reactive Forms - Read / Set value from array
我有 3 个文件:
- 从 firestore 收集我的数据并构建表单的服务
- 一个component.ts文件
- 一个component.html文件
对于我的大部分输入,我的表单都正确地从服务/表单生成器读取数据。我遇到困难的区域是使用 Angular Material Select (下拉)片段。
在我的 component.ts 文件中,我有两个选项供用户 select 使用。 select编辑后,该选项将作为字符串保存到 firestore。
正如您在下面看到的,目前我的 HTML 当前正在从其关联的 component.ts 文件中读取一个数组。理想情况下,我希望它显示来自 firestore 的当前值,并在单击它时显示两个可用选项。
如何在 HTML 中提供这两个选项以及显示 firestore 中的当前设置值?
服务
export interface IUserSettings {
usersetting_dateformat: string;
}
@Injectable()
export class SettingsService {
// Database
private settingsDocRef: AngularFirestoreDocument<any>;
settingsDocument: Observable<any>;
// User
userID: string;
// Form
editForm = new FormGroup({});
// User Settings Behaviour Subject
userSettings$: BehaviorSubject<IUserSettings>;
constructor(
private readonly afs: AngularFirestore, fb: FormBuilder) {
this.editForm = fb.group({
usersetting_dateformat: [''],
});
this.userSettings$ = new BehaviorSubject({
dateformat: 'DD/MM/YYYY',
});
}
getSettingsData() {
this.settingsDocRef = this.afs.doc(`settings/${this.userID}`);
this.settingsDocument = this.settingsDocRef.snapshotChanges();
this.settingsDocument.subscribe(value => {
const userSettings = value.payload.data() as IUserSettings;
this.userSettings$.next(userSettings);
this.editForm.patchValue(this.userSettings$.getValue());
});
}
}
Component.ts
...
dateFormats = ["DD/MM/YYYY", "MM/DD/YYYY"];
...
Component.html
<form [formGroup]="settingsService.editForm">
<mat-select placeholder="Date Format">
<mat-option *ngFor="let dateFormat of dateFormats" [value]="dateFormat"> {{dateFormat}} </mat-option>
</mat-select>
</form>
当您已经获得值然后调用表单上的 patchValue
方法时,不确定为什么要用 BehaviourSubject
不必要地使它复杂化。
您可以通过删除 BehaviorSubject
的使用来简化代码,如下所示:
export interface UserSettings {
dateFormat: string;
}
@Injectable()
export class SettingsService {
// Database
private settingsDocRef: AngularFirestoreDocument<any>;
settingsDocument: Observable<any>;
// User
userID: string;
// Form
editForm = new FormGroup({});
constructor(
private readonly afs: AngularFirestore,
fb: FormBuilder
) {
this.editForm = fb.group({
dateFormat: [],
});
}
getSettingsData() {
this.settingsDocRef = this.afs.doc(`settings/${this.userID}`);
this.settingsDocument = this.settingsDocRef.snapshotChanges();
this.settingsDocument.subscribe(value => {
const userSettings = value.payload.data() as UserSettings;
this.editForm.patchValue(userSettings);
});
}
}
然后您只需要在模板中添加 formControlName
。
<form [formGroup]="settingsService.editForm">
<mat-select placeholder="Date Format" formControlName="dateFormat">
<mat-option *ngFor="let dateFormat of dateFormats" [value]="dateFormat">
{{dateFormat}}
</mat-option>
</mat-select>
</form>
这应该可以解决您的问题。这是一个 Sample StackBlitz 供您参考。没有与您的示例相同的代码。但是应该给你一个上下文。
TL;DR; 您只需要使用该值初始化 FormControl
,然后将 formControlName
属性添加到您的表单模板即可完成此工作.
我有 3 个文件:
- 从 firestore 收集我的数据并构建表单的服务
- 一个component.ts文件
- 一个component.html文件
对于我的大部分输入,我的表单都正确地从服务/表单生成器读取数据。我遇到困难的区域是使用 Angular Material Select (下拉)片段。
在我的 component.ts 文件中,我有两个选项供用户 select 使用。 select编辑后,该选项将作为字符串保存到 firestore。
正如您在下面看到的,目前我的 HTML 当前正在从其关联的 component.ts 文件中读取一个数组。理想情况下,我希望它显示来自 firestore 的当前值,并在单击它时显示两个可用选项。
如何在 HTML 中提供这两个选项以及显示 firestore 中的当前设置值?
服务
export interface IUserSettings {
usersetting_dateformat: string;
}
@Injectable()
export class SettingsService {
// Database
private settingsDocRef: AngularFirestoreDocument<any>;
settingsDocument: Observable<any>;
// User
userID: string;
// Form
editForm = new FormGroup({});
// User Settings Behaviour Subject
userSettings$: BehaviorSubject<IUserSettings>;
constructor(
private readonly afs: AngularFirestore, fb: FormBuilder) {
this.editForm = fb.group({
usersetting_dateformat: [''],
});
this.userSettings$ = new BehaviorSubject({
dateformat: 'DD/MM/YYYY',
});
}
getSettingsData() {
this.settingsDocRef = this.afs.doc(`settings/${this.userID}`);
this.settingsDocument = this.settingsDocRef.snapshotChanges();
this.settingsDocument.subscribe(value => {
const userSettings = value.payload.data() as IUserSettings;
this.userSettings$.next(userSettings);
this.editForm.patchValue(this.userSettings$.getValue());
});
}
}
Component.ts
...
dateFormats = ["DD/MM/YYYY", "MM/DD/YYYY"];
...
Component.html
<form [formGroup]="settingsService.editForm">
<mat-select placeholder="Date Format">
<mat-option *ngFor="let dateFormat of dateFormats" [value]="dateFormat"> {{dateFormat}} </mat-option>
</mat-select>
</form>
当您已经获得值然后调用表单上的 patchValue
方法时,不确定为什么要用 BehaviourSubject
不必要地使它复杂化。
您可以通过删除 BehaviorSubject
的使用来简化代码,如下所示:
export interface UserSettings {
dateFormat: string;
}
@Injectable()
export class SettingsService {
// Database
private settingsDocRef: AngularFirestoreDocument<any>;
settingsDocument: Observable<any>;
// User
userID: string;
// Form
editForm = new FormGroup({});
constructor(
private readonly afs: AngularFirestore,
fb: FormBuilder
) {
this.editForm = fb.group({
dateFormat: [],
});
}
getSettingsData() {
this.settingsDocRef = this.afs.doc(`settings/${this.userID}`);
this.settingsDocument = this.settingsDocRef.snapshotChanges();
this.settingsDocument.subscribe(value => {
const userSettings = value.payload.data() as UserSettings;
this.editForm.patchValue(userSettings);
});
}
}
然后您只需要在模板中添加 formControlName
。
<form [formGroup]="settingsService.editForm">
<mat-select placeholder="Date Format" formControlName="dateFormat">
<mat-option *ngFor="let dateFormat of dateFormats" [value]="dateFormat">
{{dateFormat}}
</mat-option>
</mat-select>
</form>
这应该可以解决您的问题。这是一个 Sample StackBlitz 供您参考。没有与您的示例相同的代码。但是应该给你一个上下文。
TL;DR; 您只需要使用该值初始化 FormControl
,然后将 formControlName
属性添加到您的表单模板即可完成此工作.