Угловая 6 реактивная форма. Как построить форму для нескольких языков

Я работаю над CMS с Angular 6, у меня есть форма для создания страницы на двух или более языках в зависимости от поддерживаемых локалей из настроек. Во-первых, я получаю поддерживаемые локали от 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>

Как определить formControlName для поля заголовка? Я пытался использовать FormArray, но это вызывает проблему, и браузер не отвечает!

Что я должен сделать или каков наилучший подход для этого случая?

1 ответ

Решение

Я просто буду использовать .map на this.supportedLocales а затем генерировать FormGroupс помощью getFormGroupForLocale метод. Это private так как он не будет использоваться в вашем шаблоне.

Теперь, когда форма готова, сначала я свяжу всю форму с form использование тегов [formGroup]="form", После этого, так как моя форма имеет FormArrayЯ сначала должен создать упаковку div для этого. К этому div Я назначу formArrayName="translatable" который сопоставит этот div с моим translatableFormArray в formFormGroup,

В этом я буду использовать *ngFor="let group of localeFormArray; let i = index;" перебрать все FormGroupв моем FormArray и привязать их к упаковке div с помощью <div [formGroupName]="i">, Обратите внимание, как я использую formGroupName как синтаксис привязки свойств и присвоение ему индекса i из FormGroup в моем FormArray

Наконец внутри каждого input тег этого divЯ могу тогда использовать formControlName="title" а также formControlName="body" привязать к FormControlв каждом FormGroupв 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>

И для класса компонентов:

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;
  }

}

Вот пример StackBlitz для вашей ссылки.

Другие вопросы по тегам