Угловая 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 с моим translatable
FormArray
в form
FormGroup
,
В этом я буду использовать *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 для вашей ссылки.