Trying to replicate my model in a reactive form has proven challenging. I've organized FormGroups to structure the data according to my model, but I'm struggling with setting up the component to properly display the values. This suggests that there may be an issue with how my template is configured as well.
Depending on whether I am editing an existing location or creating a new one,
@Input() location: ILocation;
could potentially be undefined
. At the moment, my focus is solely on working with an existing location where location
definitely contains a value.
// location.model.ts
name: string;
...
messaging: [
{
email: {
fromName: string;
fromAddress: string;
};
}
];
...
createdAt?: string;
updatedAt?: string;
deletedAt?: string;
In the template, I'm utilizing ngClass
for validation feedback:
// location.commponent.html
<div formGroupName="messaging">
<div formGroupName="email">
...
<div [ngClass]="form.get(['messaging', 'email', 'fromName'])!.errors && (form.get(['messaging', 'email', 'fromName'])!.dirty || form.get(['messaging', 'email', 'fromName'])!.touched) ? 'red' : 'green'">
<input name="fromName"/>
</div>
<!-- fromAddress -->
</div>
</div>
Within the component, I pass the model using input binding and configure the form group(s) and form fields like this:
// location.component.ts
@Input() location: ILocation;
form: FormGroup;
...
ngOnInit(): void {
this.form = new FormGroup({name: new FormControl(this.location.name, [Validators.required]),
messaging: new FormGroup({
email: new FormGroup({
fromName: new FormControl(this.location.messaging[0].email.fromName, [Validators.required]),
fromAddress: new FormControl(this.location.messaging[0].email.fromAddress, [Validators.required]),
}),
}),
}
The current error being encountered is:
Cannot read properties of undefined (reading 'email')
If I log what's in the component:
console.log('messaging: ', this.location.messaging);
// email: {fromName: 'No Reply <<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="137d7c6176637f6a53766b8a41484847758860414149">[email protected]</a>>', fromAddress: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e58b8a978095899ca5809d9461cac8cbcfc2cd94d6dbdbe4d4">[email protected]</a>'}
I have attempted different methods such as messaging['email']
or messaging.email
messaging[0]
without success in finding the correct path.
I also question if the get()
method is correctly used in my template.
How can I correctly set up my form to read/present the data?
Update:
Unsurprisingly, a major issue was arising from sending back data in the wrong format.
Ultimately, here is the JSON structure I aim to create:
[{"email":{"fromName":"No Reply <<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d5bbbaa7b0a5b9ac95b0adb99cb3bdbab5b1beb197bab6b4">[email protected]</a>>","fromAddress":"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="254b4a574055495c65405d59527558525659f075789a767f78847893de939f9dd8">[email protected]</a>"}}]
It appears that using FormArray is necessary to send the appropriate data structure:
messaging: new FormArray([
new FormGroup({
email: new FormGroup({
fromName: new FormControl(this.location.messaging[0].email.fromName, [Validators.required]),
fromAddress: new FormControl(this.location.messaging[0].email.fromAddress, [Validators.required]),
}),
}),
]),
This poses issues in my template as I currently have:
form.get('messaging[0].email.fromAddress')
Resulting in:
Error: Cannot find control with path: 'messaging -> email'
I believe I need to somehow iterate through the FormArray
. However, this array isn't dynamic, as I will always have email
, along with only fromName
and fromAddress
.