【问题标题】:Angular Reactive Forms - Read / Set value from arrayAngular Reactive Forms - 从数组中读取/设置值
【发布时间】:2019-03-13 00:27:10
【问题描述】:

我有 3 个文件:

  • 从 Firestore 收集我的数据并构建表单的服务
  • component.ts 文件
  • component.html 文件

对于我的大部分输入,我的表单都能正确读取来自服务/表单构建器的数据。我遇到困难的区域是使用 Angular Material Select (dropdown) sn-p。

在我的 component.ts 文件中,我有一个包含两个选项的数组供用户选择。选择后,该选项将作为字符串保存到 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>

【问题讨论】:

    标签: arrays angular google-cloud-firestore angular-reactive-forms


    【解决方案1】:

    不知道为什么当您已经获得值然后您在表单上调用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 属性添加到您的表单模板即可完成这项工作。

    【讨论】:

    • 谢谢哥们! - 只是缺少表单控件名称。行为主题存在于应用程序的其他区域。但你的回答有帮助。谢谢! :)
    • 这太棒了。这帮助我弄清楚如何根据 url 中传递的 id 在更新字段中显示值。
    猜你喜欢
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 2018-08-24
    • 2020-02-20
    • 1970-01-01
    • 2019-07-19
    • 2020-07-16
    • 2019-11-26
    相关资源
    最近更新 更多