Angular 6 反应形式。如何为多种语言构建表单

Angular 6 reactive form. How to build form for multiple languages

我正在使用 Angular 6 开发 CMS,我有一个表单可以创建包含两种或更多语言的页面,具体取决于设置中支持的语言环境。 首先,我从 api 获取支持的语言环境,假设响应有 2 个语言环境 (en - fr)。 因此,对于每种语言,我想在表单内构建一个选项卡,它具有自己的语言环境,例如 en['title']、en['body']、fr['title']、fr['body']. 我尝试构建这样的表单:

let forms = [];
for(let lang of this.supportedLocales) {
    forms.push(this.fb.group({
      title: ['', [Validators.required]],
      body: ['', [Validators.required]]
    }))
  }

  this.form = this.fb.group({
    template: ['default', [Validators.required]],
    is_home: [0],
    translatable: this.fb.array(forms)
  });
}

并且在 HTML 中:

<div class="tab-content">
    <div *ngFor="let lang of supportedLocales"
         class="tab-pane {{lang.locale === currentLang ? 'active' : ''}}"
         id="{{ 'tab_'+ lang.locale}}">

      <div class="form-group">
        <label [attr.for]="'title'+lang.locale">{{ translateField('page::pages.title') }}</label>
        <input formControlName="?" [attr.id]="'title'+lang.locale" class="form-control">
      </div>
    </div>
  </div>

如何定义title字段的formControlName? 我曾尝试使用 FormArray,但它导致了问题,浏览器没有响应!

对于这种情况我应该怎么办或最好的方法是什么?

我将只在 this.supportedLocales 上使用 .map,然后使用 getFormGroupForLocale 方法生成 FormGroup。它是 private,因为它不会在您的模板中使用。

表单准备就绪后,首先我将使用 [formGroup]="form" 将整个表单绑定到 form 标记。之后,因为我的表单有一个 FormArray,我首先必须为它创建一个包装 div。对于这个 div,我将分配 formArrayName="translatable",它将把这个 div 映射到我在 form FormGroup 中的 translatable FormArray

在其中,我将使用 *ngFor="let group of localeFormArray; let i = index;" 遍历我的 FormArray 中的所有 FormGroup 并使用 [=31 将它们绑定到包装 div =].请注意我是如何使用 formGroupName 作为 属性 绑定语法并将其分配给 FormGroup 的索引 i 在我的 FormArray

最后在这个 div 的每个 input 标签内,然后我可以使用 formControlName="title"formControlName="body" 绑定到每个 FormControl =14=]s 在 FormArray.

方法如下:

<form [formGroup]="form">
  template
  is_home
  translatable
  <label for="template">Template</label>
  <input type="text" id="template" formControlName="template">

  <br><br>

  <label for="is_home">Is Home</label>
  <input type="text" formControlName="is_home" id="is_home">

  <br><br>

  <h1>translatable</h1>
  <div formArrayName="translatable">
    <div *ngFor="let group of localeFormArray; let i = index;">
      <div [formGroupName]="i">
        <label 
          [for]="'title'+supportedLocales[i].lang.locale">
          {{ translateField('page::pages.title') }}
        </label>
        <input 
          formControlName="title" 
          [id]="'title'+supportedLocales[i].lang.locale" 
          class="form-control">

        <br><br>

        <label 
          [for]="'title'+supportedLocales[i].lang.locale">
          {{ translateField('page::pages.title') }}
        </label>
        <input 
          formControlName="body" 
          [id]="'title'+supportedLocales[i].lang.locale" 
          class="form-control">

      </div>
    </div>
  </div>


</form>

对于组件 Class:

import { Component } from '@angular/core';
import { FormGroup, FormControl, FormBuilder, Validators, FormArray } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  form: FormGroup;
  supportedLocales = [
    { lang: { locale: 'en-US' } },
    { lang: { locale: 'en-FR' } },
  ];

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.form = this.fb.group({
      template: ['default', [Validators.required]],
      is_home: [0],
      translatable: this.fb.array(this.supportedLocales.map(locale => this.getFormGroupForLocale(locale)))
    });
  }

  private getFormGroupForLocale(language) {
    return this.fb.group({
      title: [language.lang.locale + 'Title', [Validators.required]],
      body: [language.lang.locale+'Body', [Validators.required]]
    });
  }

  ...

  get localeFormArray() {
    return (<FormArray>this.form.get('translatable')).controls;
  }

}

这里有一个 Sample StackBlitz 供您参考。