Reputation: 1200
I have a scenario where I'm using a form displayed inside a modal popup which is created using ng-bootstrap
. Within the modal I'm using a custom component to display validation messages for each form field but it doesn't look like that component is being picked up and executed by the Angular lifecycle.
I open the popup from it's parent component using a button:
<button type="button" (click)="openFormModal()">Add something</button>
Which executes the following code where MyModalComponent
has been imported:
openFormModal() {
const modalRef = this.modalService.open(MyModalComponent);
}
The modal itself is fairly unremarkable apart from the custom validation-messages
component. The code sample has various things omitted for brevity:
<div class="modal-body">
<form [formGroup]="myForm" class="form">
<input type="text" [ngClass]="'form-control'" formControlName="name" required maxlength="100">
<validation-messages [control]="myForm.controls.names" controlName="Name"></validation-messages>
</form>
</div>
The validation-messages
component is as follows:
import { Component, Input } from '@angular/core';
import { FormControl } from '@angular/forms';
import { ValidationService } from './notifications.validation.service';
@Component({
selector: 'validation-messages',
template: `<div *ngIf="errorMessage !== null" class="invalid-notification">{{errorMessage}}</div>`
})
export class ValidationMessages {
@Input() control: FormControl;
@Input() controlName: string;
constructor() { }
get errorMessage() {
for (let propertyName in this.control.errors) {
if (this.control.errors.hasOwnProperty(propertyName) && (this.control.touched && this.control.invalid)) {
return ValidationService.getValidatorErrorMessage(propertyName, this.controlName, this.control.errors[propertyName]);
}
}
return null;
}
}
validation-messages
works perfectly in a standard form i.e. not in a modal but when the HTML for the modal renders on the screen the validation-messages
renders as follows:
<validation-messages controlname="Name"></validation-messages>
Instead of how it renders normally:
<validation-messages controlname="Business name" ng-reflect-control="[object Object]" ng-reflect-control-name="Business name">
<!--bindings={
"ng-reflect-ng-if": "false"
}-->
</validation-messages>
I'm pretty new to Angular and I'm sure that it's something pretty fundamental that I'm missing.
It's probably also worth mentioning that I had to add schemas: [CUSTOM_ELEMENTS_SCHEMA],
to my app.module.ts
to get the modal to not complain about the validation-messages
component being present in the HTML.
Any help would be greatly appreciated.
Edit
validation-messages
is also part of a notifications module:
import { NgModule } from "@angular/core";
import { ValidationMessages } from "./notifications.validationmessages";
import { CommonModule } from '@angular/common';
@NgModule({
imports: [CommonModule],
declarations: [ValidationMessages],
exports: [ValidationMessages]
})
export class NotificationsModule {}
Upvotes: 0
Views: 1978
Reputation: 6163
The error message regarding adding CUSTOM_ELEMENTS_SCHEMA
gave a clue that Angular did not know about the ValidationMessages
component. As your ValidationMessages
component is part of the NotificationsModule
you need to ensure that this module finds it way up into the global application module (often app.module.ts
).
Modifying app.module.ts
as follows should fix the issue:
@NgModule({
imports: [
...,
NotificationsModule
],
declarations: [
...
],
bootstrap: [
...
]
})
export class AppModule {
}
Regarding the comment "Does adding that make the component available at the root level?" - it will only be available at the root level if you add it to the exports
of the NotificationsModule
- like this:
import { NgModule } from "@angular/core";
import { ValidationMessages } from "./notifications.validationmessages";
import { CommonModule } from '@angular/common';
@NgModule({
imports: [CommonModule],
declarations: [ValidationMessages],
exports: [ValidationMessages] // Available at root level/other modules
})
export class NotificationsModule {}
Upvotes: 1