I have created a custom control using ControlValueAccessor that is composed of an input[type=text]
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 disable()
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
EDIT
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.
EDIT
This is my custom control:
@Component({ selector: 'extended-datepicker', templateUrl: './extended-datepicker.component.html', styleUrls: ['./extended-datepicker.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, 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()" *ngIf="selectedDate"> <i class="fa fa-chevron-left"></i> </span> <input #textInput [textMask]="{mask: mask}" [(ngModel)]="selectedDateString" (ngModelChange)="inputChange()" class="form-control" [required]="required" [disabled]="disabled" (keyup)="onKeyPressed($event)"> <span class="input-group-addon" role="button" (click)="nextDay()" *ngIf="selectedDate"> <i class="fa fa-chevron-right"></i> </span> </div> <div *ngIf="isDatepickerActive" class="datepicker-wrapper"> <datepicker [(ngModel)]="selectedDate" (ngModelChange)="dateChange()" [showWeeks]="false" [required]="required" [formatDay]="dd" [formatMonth]="MM" [formatYear]="yyyy" [disabled]="disabled"> </datepicker> </div> </div> <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"> </button> </div> </div>
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 disable()
call inside my extended-datepicker and act accordingly?
If you set disabled to true when you set up this control in your component class, the disabled attribute will actually be set in the DOM for you. We recommend using this approach to avoid 'changed after checked' errors. Example: form = new FormGroup({ first: new FormControl({value: 'Nancy', disabled: true}, Validators.
What are form controls in Angular? In Angular, form controls are classes that can hold both the data values and the validation information of any form element. Every form input you have in a reactive form should be bound by a form control. These are the basic units that make up reactive forms.
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 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With