У меня есть три компонента: GalleryAddComponent для добавления нового элемента, GalleryItemComponent, для редактирования элемента, FieldsComponent, форма, которую я хочу использовать в компонентах: GalleryAddComponent и GalleryItemComponent. Все компоненты находятся внутри GalleryComponent. Но когда я перехожу к компоненту GalleryAddComponent, чтобы добавить новый элемент, я получаю сообщение об ошибке: ERROR TypeError: Cannot read property 'controls' of undefined. Также в компоненте: GalleryItemComponent.
Помогите решить эту проблему, чтобы логика редактирования и добавления работала правильно.
шаблон GalleryAddComponent
<div class = "card">
<div class = "card-body">
<form [formGroup] = "angForm" novalidate>
<app-fields [formGroup] = "angForm"></app-fields>
<div class = "form-group but-group">
<button (click) = "addPost(title.value, url.value); angForm.reset(title.value, url.value)"
[disabled] = "angForm.pristine || angForm.invalid"
class = "btn btn-primary">Add
</button>
<a routerLink = "/" class = "btn btn-danger">Back</a>
</div>
</form>
</div>
</div>код GalleryAddComponent
export class GalleryAddComponent implements OnInit {
angForm: FormGroup;
isAdded: boolean = false;
constructor(private fb: FormBuilder, private galleryService: GalleryService) {}
ngOnInit() {
this.angForm = this.fb.group({
title: ['', Validators.required],
url: ['', Validators.required]
});
}
addPost(title: string, url: string): void {
this.galleryService.add(title, url).subscribe(res => {
this.isAdded = true;
});
}
}шаблон GalleryItemComponent
<div class = "card" *ngIf = "toggleEdit">
<h4>Edit your post</h4>
<div class = "card-body">
<form [formGroup] = "angForm" novalidate>
<app-fields [formGroup] = "angForm"></app-fields>
<div class = "form-group but-group">
<input type = "button"
(click) = "updatePost(title.value, url.value)"
[disabled] = " angForm.invalid"
class = "btn btn-primary" value = "Update Post">
</div>
</form>
</div>
</div>код GalleryItemComponent
export class GalleryItemComponent implements OnInit {
pic: Picture;
angForm: FormGroup;
constructor(private route: ActivatedRoute,
private galleryService: GalleryService, private fb: FormBuilder) {}
ngOnInit() {
this.angForm = this.fb.group({
title: ['', Validators.required],
url: ['', Validators.required]
});
this.showPost();
}
showPost(): void {
this.route.params.subscribe(params => {
this.galleryService.getPicture(params['id']).subscribe(res => {
this.pic = res;
this.angForm.setValue({title: res.title, url: res.url})
})
})
}
updatePost(title: string, url: string): void {
this.route.params.subscribe(params => {
this.galleryService.update(title, url, params['id']).subscribe(res => {
if (res.id === this.pic.id) {
this.pic.title = title;
this.pic.url = url;
}
});
});
}
}шаблон FieldsComponent
<div [formGroup] = "formGroup">
<div class = "form-group">
<label class = "col-md-4">Picture Title</label>
<input type = "text" class = "form-control" formControlName = "title" minlength = "1" #title/>
</div>
<div *ngIf = "angForm.controls['title'].invalid && (angForm.controls['title'].dirty || angForm.controls['title'].touched)"
class = "alert alert-danger">
<div *ngIf = "angForm.controls['title'].errors.required">
Title is required.
</div>
</div>
<div class = "form-group">
<label class = "col-md-4">Picture Address (url)</label>
<input type = "url" class = "form-control" formControlName = "url" #url pattern = "https?://.+"
title = "Include http://"/>
</div>
<div *ngIf = "angForm.controls['url'].invalid && (angForm.controls['url'].dirty || angForm.controls['url'].touched)"
class = "alert alert-danger">
Address(url) is required.
<div *ngIf = "angForm.controls['url'].errors.required ">
</div>
</div>
</div>код FieldsComponent
export class FieldsComponent implements OnInit {
@Input() formGroup: FormGroup;
constructor() {}
ngOnInit() {}
}@Roy stackblitz.com/edit/angular-cvf4ut Я подумываю вырезать те же входные данные с валидацией из компонентов «GalleryAddComponent» и «GalleryitemComponent» и вставить их в отдельный компонент. Затем подключите этот компонент в форме в компоненте «GalleryAddComponent» и в форме компонента «GalleryitemComponent». Но как это реализовать, не нарушая логики?
Не могли бы вы исправить свой проект stackblitz, чтобы его можно было запустить?
@ Балаж Такач stackblitz.com/github/gorillasz/gallery



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы получаете эту ошибку, потому что вы ссылаетесь на angForms.controls в своем FieldsComponent, который имеет только одну переменную: formGroup.
Просто замените angForms в HTML-коде шаблона на formGroup, и проблема должна быть решена.
<div [formGroup] = "formGroup">
<div class = "form-group">
<label class = "col-md-4">Picture Title</label>
<input type = "text" class = "form-control" formControlName = "title" minlength = "1" #title />
</div>
<div *ngIf = "formGroup.controls['title'].invalid && (formGroup.controls['title'].dirty || formGroup.controls['title'].touched)"
class = "alert alert-danger">
<div *ngIf = "formGroup.controls['title'].errors.required">
Title is required.
</div>
</div>
<div class = "form-group">
<label class = "col-md-4">Picture Address (url)</label>
<input type = "url" class = "form-control" formControlName = "url" #url pattern = "https?://.+" title = "Include http://" />
</div>
<div *ngIf = "formGroup.controls['url'].invalid && (formGroup.controls['url'].dirty || formGroup.controls['url'].touched)"
class = "alert alert-danger">
Address(url) is required.
<div *ngIf = "formGroup.controls['url'].errors.required ">
</div>
</div>
</div>
Я сделал это, ошибка была такой же, поэтому я создал свой проект в «StackBlitz» без компонента «FieldsComponent», чтобы показать мне, как поместить поля в отдельный компонент и подключиться к компонентам: «GalleryAddComponent» и «GalleryitemComponent», не теряя своей логики
Я немного обновил свой ответ - проверьте, работает ли это для вас. (Кроме того, ни одна из предоставленных вами ссылок StackBlitz на самом деле не показывала полученную вами ошибку, поэтому я воссоздал ее локально.)
[formGroup] = "formGroup", это не нужно в элементе div
Я думаю, что простое решение здесь - настроить группу форм в родительском компоненте и передать ее дочерним компонентам в качестве входных данных, поэтому она передается дочернему компоненту до загрузки дочернего компонента html.
Другое решение, которое я бы порекомендовал, - это использовать технику разрешения, предлагаемую Angular, это позволяет загружать все данные до загрузки компонента с довольно простой настройкой.
Вот несколько ссылок:
Невозможно прочитать "элементы управления" свойства undefined. Эта ошибка может появиться только потому, что вместо formGroup вы использовали angForm. Попробуйте заменить его, как поделился @Wrokar. Я также понимаю, что вы хотите отображать сводные сообщения об ошибках. Поэтому вместо того, чтобы делать это в html для каждого элемента управления формы, вы должны сделать это в component.ts и сделать его более общим, подписавшись на изменение значения каждого элемента управления, как показано ниже, и показать консолидированное сообщение об ошибке.
for (const field in this.formGroup.controls) { // 'field' is a string
const control = this.form.get(field); // 'control' is a FormControl
control.valueChanges.subscribe(
(res) => {
// check if it is pristine, dirty, invalid, touched, pattern match if
any
// you can access control.errors
// create the consolidated list and append it in the list of error
messages
}
)
}
Лучше сделать его универсальным, потому что завтра ваша форма может иметь дополнительные поля, и тогда вам не придется менять FieldsComponent.
Не могли бы вы сделать из ваших файлов пример StackBlitz? См. stackblitz.com