Consider the following simple example in a component of an Angular 4 application. It shows a simple HTML form with two input fields. One input field is directly implemented, the second is within a child component:
<form #personForm="ngForm">
<input type="text" required name="firstname [(ngModel)]="firstname"/>
<app-smart-input required [(model)]="lastname"></app-smart-input>
<button [disabled]="personForm.valid === false">Send</button>
</form>
The child component is defined as follows:
import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
@Component({
selector: "app-smart-input",
templateUrl: "./smart-input.component.html",
styleUrls: ["./smart-input.component.css"]
})
export class SmartInputComponent {
////////////////
// PROPERTIES //
////////////////
@Input() model: string;
@Output() modelChange: EventEmitter<string> = new EventEmitter<string>();
@Input("required") required: boolean = false;
/////////////
// METHODS //
/////////////
updateChanges() {
this.modelChange.emit(this.model);
}
}
with the following html:
<input type="text" [required]="required" [(ngModel)]="model" (ngModelChange)="updateChanges()" />
Now updating the models work perfectly fine (firstname
and lastname
are defined by the user input as expected).
What I would like to achieve is that the button gets disabled unless both fields are filled in. Note the required
flag in the <input>
implementations, so the values should not be null/undefined.
But unfortunately, the button is now only disabled if the firstname
is not well defined. But the form doesn't care about the lastname
.
How would I achieve this?
Note: Angular 2 creating reactive forms with nested components is simular, but I use a template driven form, not a reactive form. But it can be probably adapted somehow?
You'll need to implement
ControlValueAccessor
if you want your SmartInputComponent to participate as part of an Angular Form.This means providing a way for your custom component to have changes propagate between it and the parent form. Here's an implementation using your SmartInputComponent as a basis.
with a template like:
Then when consuming your component, have it participate in form like the standard controls (which Angular provides the
ControlValueAccessor
implementation for you).If run this form you'll see the
personForm
now has both the first and second name values captured.Also see the Angular documentation on ControlValueAccessor