Siri0S Siri0S - 11 months ago 143
Javascript Question

Angular 2 - Custom Form Control - Disable

I have created a custom control using ControlValueAccessor that is composed of an

and a datepicker.

When I use it in template-driven forms everything works fine.
But when I use the model-driven approach (reactive forms), the
method on the form control doesn't seem to have any effect whatsoever.

Is it possible to disable/enable my custom control programmatically as I do with every other form control in model-driven forms


I should note that I'm using Angular v2.1.0 and that my methodology is pretty much the same as this as I have been using it as a guide.


This is my custom control:

selector: 'extended-datepicker',
templateUrl: './extended-datepicker.component.html',
styleUrls: ['./extended-datepicker.component.scss'],
providers: [
useExisting: forwardRef(() => ExtendedDatepickerComponent),
multi: true
export class ExtendedDatepickerComponent implements OnInit, ControlValueAccessor {
isDatepickerActive: boolean = false;
_selectedDate: Date;
selectedDateString: string = "";
@Input() disabled: boolean;
@Input() mask: any;
@Input() required: boolean;

@ViewChild('textInput') textInput: ElementRef;

get selectedDate(): Date {
return this._selectedDate;

set selectedDate(value: Date) {
this.selectedDateString = moment(value).format(STANDARD_DATE_FORMAT);
this._selectedDate = value;

propagateChange: Function;

@ViewChild(DatePickerComponent) datepicker: DatePickerComponent;

constructor() {

writeValue(value: Date) {
if (value) {
this.selectedDate = value;
this.selectedDateString = moment(value).format(STANDARD_DATE_FORMAT);

registerOnTouched(): void {

registerOnChange(fn: Function) {
this.propagateChange = fn;
// ...

This is the control's template:

<div class="calendar-wrapper row-small-margin"
(clickOutside)="isDatepickerActive = false;">

<div class="col-xs-10 col-small-padding">
<div class="input-group">

<span class="input-group-addon" role="button" (click)="prevDay()"
<i class="fa fa-chevron-left"></i>

<input #textInput [textMask]="{mask: mask}"
class="form-control" [required]="required"
[disabled]="disabled" (keyup)="onKeyPressed($event)">

<span class="input-group-addon" role="button" (click)="nextDay()"
<i class="fa fa-chevron-right"></i>

<div *ngIf="isDatepickerActive" class="datepicker-wrapper">
<datepicker [(ngModel)]="selectedDate" (ngModelChange)="dateChange()"
[showWeeks]="false" [required]="required"
[formatDay]="dd" [formatMonth]="MM" [formatYear]="yyyy"

<div class="col-xs-2 col-small-padding">
<button class="btn btn-sm btn-datepicker" [disabled]="disabled"
(click)="toggleDatePicker()" type="button">
<img src="/assets/img/image.png">


And this is what I do in my form component:

this.myForm.controls['pickDate'].valueChanges.subscribe(val => {
if (!val) {
this.myForm.controls['date'].disable(); // This line here does nothing

How is it possible to respond to that
call inside my extended-datepicker and act accordingly?

Answer Source

Your component needs to implement the setDisabledState function which is defined in the ControlValueAccessor interface (see docs).

E.g. (assuming the renderer has been injected in the constructor):

setDisabledState(isDisabled: boolean) {
    this.renderer.setElementProperty(this.textInput.nativeElement, 'disabled', isDisabled);
    // disable other components here