Angular PatchValue не работает при вызове из другого компонента
У меня есть один компонент, который получает коллекцию документов из хранилища и отображает их в таблице, а другой - с реактивной формой для добавления новых записей в таблицу.
Я работаю над тем, чтобы позволить пользователю нажать кнопку в таблице, которая затем заполнит компонент реактивной формы данными из этой строки.
Вот моя форма в компоненте А:
inventoryForm = new FormGroup({
name: new FormControl('', Validators.required),
date: new FormControl('', Validators.required),
amount: new FormControl('', Validators.required),
comment: new FormControl('', Validators.required),
carried: new FormControl('', Validators.required),
});
Если я добавлю кнопку в componentA.html, которая вызывает функцию, подобную этой в componentA
testPatch() {
this.inventoryForm.patchValue({ name: 'Test123' });
}
Форма обновляется должным образом (ввод имени заполняется Test123).
Однако, если у меня есть кнопка в componentB.html, которая вызывает функцию в componentB, которая затем вызывает функцию patchValue в componentA, патч не работает.
Я импортирую componentA в componentB для вызова функции во время прохождения через идентификатор документа.
Есть ли что-то простое, что я упускаю, или лучший способ попробовать это сделать?
Обновление: я сталкиваюсь с проблемой, когда группа форм возвращает ноль, я собираюсь добавить некоторые дополнительные части кода.
Мне пришлось обновить [provider] в app.module.ts, чтобы добавить FormGroupDirective, или я получу ошибку стекового инжектора при попытке инициализации FormGroupDirective в конструкторе моего компонента.
app.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
import { InventoryService } from './inventory.service';
import { inventory_item } from './inventory_item';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private inventoryService: InventoryService) {
}
inventoryForm = new FormGroup({
name: new FormControl('', Validators.required),
date: new FormControl('', Validators.required),
amount: new FormControl('', Validators.required),
comment: new FormControl('', Validators.required),
carried: new FormControl('', Validators.required),
});
submitted = false;
update = false;
submittedItem: inventory_item = {
name: '',
date: '',
amount: 0,
comment: '',
carried: '',
}
onSubmit() {
this.submitted = true;
const name = this.inventoryForm.get('name').value;
const date = this.inventoryForm.get('date').value;
const amount = this.inventoryForm.get('amount').value;
const comment = this.inventoryForm.get('comment').value;
const carried = this.inventoryForm.get('carried').value;
this.inventoryService.addInventory({ name, date, amount, comment, carried })
this.submittedItem = this.inventoryForm.value
}
}
app.component.html
<app-inventory-list></app-inventory-list>
<div [hidden]="submitted">
<form [formGroup]="inventoryForm" (ngSubmit)="onSubmit()">
<label>
Item Name:
<input type="text" formControlName="name">
</label>
<label>
Date Added:
<input type="text" formControlName="date">
</label>
<label>
Amount:
<input type="number" formControlName="amount">
</label>
<label>
Comment
<input type="text" formControlName="comment">
</label>
<label>
Carried by:
<input type="text" formControlName="carried">
</label>
<br />
<button type="submit" [disabled]="!inventoryForm.valid">Submit</button>
</form>
</div>
<app-item-management></app-item-management>
<div [hidden]="!submitted">
<h2>Item Added</h2>
Name: {{submittedItem.name}}
<br />
Date: {{submittedItem.date}}
<br />
Amount: {{submittedItem.amount}}
<br />
Comment: {{submittedItem.comment}}
<br />
Carried by: {{submittedItem.carried}}
<br />
<button type="button"
class="btn btn-default"
(click)="inventoryForm.reset();
submitted=false">
New Loot!
</button>
</div>
пункт-management.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { InventoryService } from '../inventory.service';
import { FormGroupDirective, FormGroup, ControlContainer, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-item-management',
templateUrl: './item-management.component.html',
styleUrls: ['./item-management.component.css'],
viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }]
})
export class ItemManagementComponent implements OnInit {
constructor(private inventoryService: InventoryService, private parentForm: FormGroupDirective) {
}
editItem: any;
ngOnInit() {
}
testPatch() {
//this.parentForm.form.patchValue({ name: 'Test123' });
console.log(this.parentForm.form)
};
updateInventory(updateId: string) {
//this.parentForm.inventoryForm.patchValue({ name: 'Test123' });
this.parentForm.form.patchValue({ name: 'Test123' });
this.inventoryService.getUpdateInventoryItem(updateId)
.then((doc) => {
if (doc.exists) {
console.log("Document data:", doc.data());
this.editItem = doc.data();
console.log("EditItem:", this.editItem)
} else {
console.log("No such document!");
}
}).catch(function (error) {
console.log("Error getting document:", error);
});
};
}
пункт-management.component.html
<button type="button"
class="btn btn-default"
(click)="testPatch()">
Patchtest
</button>
Поэтому, когда я нажимаю кнопку "patch test", консоль выводит "null" для возвращенного объекта, или я получаю:
Cannot read property 'patchValue' of null
at ItemManagementComponent.push..
1 ответ
Лучший подход - создать форму верхнего уровня, а затем обернуть ваш дочерний компонент внутри этого компонента.
app.component.ts
<form [formGroup]="form">
<input type="text" formControlName="name">
<app-component-b></app-component-b>
</form>
Внутри дочернего компонента используйте Viewproviders, чтобы получить экземпляр родительской формы для исправления значения, используя
componentb.component.ts
import { Component, OnInit } from '@angular/core';
import { ControlContainer, FormGroupDirective } from '@angular/forms';
@Component({
selector: 'app-component-b',
templateUrl: './component-b.component.html',
styleUrls: ['./component-b.component.css'],
viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }]
})
export class ComponentBComponent implements OnInit {
constructor(private parentForm: FormGroupDirective) { }
ngOnInit() {
}
patchValue() {
this.parentForm.form.patchValue({ name: 'fromChildComponentB' });
}
}