#angular #typescript #angular-reactive-forms
#angular #typescript #угловые реактивные формы
Вопрос:
Я тренируюсь с angular reactiveforms и создаю интерфейс, роль которого будет заключаться в подаче часто задаваемых вопросов. Первым уровнем формы будут темы, вторым — вопросы, а третьим — ряд шагов, которым необходимо следовать.
Хотя второй уровень соответствует первому, третий вызывает у меня боль. Терминал выводит как controls.registerOnChange is not a function
, так и Cannot find control with path: 'questions -> steps'
.
Я хотел бы понять, где и почему я совершаю ошибку.
мой компонент.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray } from '@angular/forms'
import { ThemeService } from 'src/app/service/theme.service';
@Component({
selector: 'app-edition-form',
templateUrl: './edition-form.component.html',
styleUrls: ['./edition-form.component.css']
})
export class EditionFormComponent implements OnInit {
constructor(private fb:FormBuilder, private ts:ThemeService) { }
form:FormGroup;
themes;
s_theme;
questions;
s_question;
steps;
s_step;
msg;
hitButton:string;
ngOnInit() {
this.s_theme==0;
this.s_question=null;
this.s_step=null;
this.ts.getThemesList().subscribe(
data => this.themes = data,
err => this.msg = err
)
this.form = this.fb.group({
id:'',
libelle:'',
//questions: this.fb.array([this.fb.control('')])
questions: this.fb.array([this.initQuestion()])
})
}
initQuestion(){
return this.fb.group({
id:'', libelle:'', steps: this.fb.array([this.initStep()])
})
}
initStep(){
return this.fb.group({
id:'', libelle:'', path:''
})
}
validateForm(){
}
// Définition d'un getter pour récupérer le tableau qu'on souhaite construire dans le formulaire
get questionList(){
return this.form.get('questions') as FormArray
}
get stepsList(){
return this.form.get('questions').get('steps') as FormArray
}
// ajouter des contrôles dans les éléments de ce tableau
addQuestion(){
this.questionList.push(this.fb.control(''))
}
// sélection dans les listes déroulantes
setTheme(theme){
if(theme.libelle==null){
this.s_theme = null;
this.questions = null;
this.removeControls(this.questionList)
}else{
this.s_theme = theme.id
this.ts.getQuestions(theme.id).subscribe(
data=> {
this.questions = data
this.removeControls(this.questionList)
this.questions.forEach(element => {
this.questionList.push(this.fb.control(element.libelle)) //permet de publier la liste des questions dans le formulaire
});
},
err => this.msg = err
)
}
}
removeControls(list:FormArray){
while(list.controls.length!==0){ //permet de supprimer des controles
list.removeAt(0)
}
}
setQuestion(question){
this.s_question = question.id
this.ts.getSteps(this.s_theme, question.id).subscribe(
data => {
this.steps = data
},
err=>this.msg=err
)
console.log(question)
}
setStep(step){
this.s_step = step.id;
}
handleSubmit(formData){
console.log(formData)
}
button(number){
this.hitButton = number;
if(this.hitButton=="01"){
}else if(this.hitButton =="02"){
this.addQuestion()
}
console.log(this.hitButton)
}
}
Мой component.html
<form [formGroup]=form (submit)=handleSubmit(this.form.value)>
<div>
<app-dropdown label="Thème" [list]="this.themes" (selection)="setTheme($event)"></app-dropdown>
</div>
<div *ngIf="this.s_theme==null">
<p>ou</p>
<input type="text" placeholder="Saisir nouveau thème" class="form-control" formControlName="libelle" />
</div>
<hr>
<app-dropdown label="Questions" [list]="this.questions" (selection)="setQuestion($event)"></app-dropdown>
<div>
<div class="d-flex align-items-center">
<div class="col-1">
Ou
</div>
<div class="col-8">
<app-bouton class="" id=02 text="Ajouter une question" (hit)=button($event)></app-bouton>
</div>
</div>
<div formArrayName="questions">
<div *ngFor="let question of questionList.controls; let i=index">
<div class="row">
<div class="col-1">
<p>{{i 1}}</p>
</div>
<div class="col-8">
<input type="text" class="form-control" placeholder="Saisissez votre question" [formControlName]="i" />
<div formArrayName="steps">
<div *ngFor="let step of questionList['controls'].steps['controls']; let j=index">
<input type="text" class="form-control" placeholder="Saisissez votre étape" [formControlName]="j"/>
</div>
</div>
</div>
</div>
</div>
<hr>
</div>
</div>
<hr>
<button type="submit">Enregistrer</button>
</form>
Заранее благодарю вас за то, что помогаете мне прогрессировать.
Ответ №1:
Похоже, что steps
выполняется поиск непосредственно под questions
, а не в реальном.
Вы могли бы попробовать что-то вроде этого:
<ng-container [formGroup]="form.questions.get(i)">
<div formArrayName="steps">
<div *ngFor="let step of questionList['controls'].steps['controls']; let j=index">
<input type="text" class="form-control" placeholder="Saisissez votre étape" [formControlName]="j"/>
</div>
</div>
</ng-container>
Я не совсем уверен в синтаксисе, но идея состоит в том, чтобы сообщить Angular, с каким вопросом он работает.