具有动态变化的子表单的复杂 Angular 表单

Complex Angular forms with dynamically changing sub-forms

这是来自 Google 日历的屏幕截图。如何在 Angular/Material(当前分别为 4.4.4 和 2.0.0-beta.12)中构建此界面?

注意:我发现 Angular 和 Material 有两个特别具有挑战性的功能。

  1. 整个表格根据第一个选择框而变化。 "Repeat daily" 计算天数,而 "repeat weekly" 提供一周中特定日期的复选框。 ("Repeat monthly" 也提供独特的选项。)我真的更喜欢模块化解决方案,我可以在其中将相互排斥的子表单分解为它们自己的 component/formGroup。在 ngIf 存在的情况下管理验证也让我头疼。

  2. "Ends:" 块是一个组合单选按钮,带有用于某些选项的数字和日期输入。我不确定如何使用 angular+material 来近似,或者如何设置验证。我很乐意让 "Ends" 也成为一个选择框,但在那种情况下,我不想为后面的 0 或 1 个输入字段使用单独的 component/formGroup。所以我不能将它完全简化为问题 #1 的一个实例。

我不得不为一个应用程序构建相同的组件,虽然它基于 OSX 提醒计划程序,但大致相同。

最好只关注 "end" 选择,因为可以在整个组件中应用相同的概念。 end FormGroup是一个更大的FormGroup中的一个控件,看起来像这样

end: this.fb.group({
  // default to 'never'. Can also be 'date' or 'count'
  selection: 'never',
  // default the date to one week from now
  date: [startOfDay(addDays(oneHourFromNow, 7)), Validators.required],
  // default to only repeating once
  count: [1, [Validators.required, CustomValidators.number(this.countLimits)]]
})

显然,如果您按原样提交此表单,它将包含一个没有多大意义的值。为了解决这个问题,您需要根据需要 enabledisable datecount 控件。当抽象控件被禁用时,它不会包含在表单值中。

this.endGroup.get('selection').valueChanges
  .startWith(null)
  .subscribe(() => {
    // if the selection value is 'never',
    // disable both the 'date' and 'count' controls

    // if the selection value is 'date',
    // enable 'date' control and disable 'count' control

    // if the selection value is 'count',
    // enable 'count' control and disable 'date' control
  });

结束选择器的模板看起来有点像这样,

<mat-select formControlName="selection">...</mat-select>

<ng-container *ngIf="selectionControl.value === 'date'">
  <!-- input with datepicker -->
</ng-container>

<ng-container *ngIf="selectionControl.value === 'count'">
  <!-- input with type="number" -->
</ng-container>
Todd Motto 的

This article 也帮助将表单组封装到它们自己的表示组件中。我很乐意解释更多,但这绝对是我必须构建的最复杂的组件,因此在一个答案中包含的内容有点多。