I am trying to create a custom component that wraps the Kendo Editor so I can display a label and validation messages all within the same component. The goal is to make it reuseable and self-contained. The majority of it is working except for clearing out the form. When reset is called on the parent form (and then the form control) the backing value is reset to null but the display value remains the same.
The code for the custom component is below. I feel like either I'm missing something or the implementation is not correct. Thanks in advance.
rich-text.component.ts
import { Component, forwardRef, Injector, Input, OnDestroy, OnInit } from '@angular/core';
import { ControlValueAccessor, FormControl, FormControlDirective, FormControlName, FormGroupDirective, NgControl, NgModel, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator, Validators } from '@angular/forms';
import { PaletteSettings } from '@progress/kendo-angular-inputs';
import { ERROR_MESSAGES } from 'core/constants';
import { noWhitespaceValidator } from 'core/helpers/customValidators';
import { HTMLUtilities } from 'core/services/utility/html-utilities.service';
import { Subscription } from 'rxjs';
@Component({
selector: 'rich-text',
templateUrl: './rich-text.component.html',
styleUrls: ['./rich-text.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => RichTextComponent)
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => RichTextComponent),
multi: true
}
]
})
export class RichTextComponent implements OnInit, OnDestroy, ControlValueAccessor, Validator {
@Input() label: string = 'Please supply label';
@Input() placeholder: string = 'Please provide a value';
public paletteSettings: PaletteSettings = {
palette: 'basic'
}
formControl = new FormControl('', [Validators.required, noWhitespaceValidator]);
subs: Subscription[] = [];
_htmlUtilities: HTMLUtilities;
onChange: any = () => {};
onTouch: any = () => {};
constructor(htmlUtilities: HTMLUtilities) {
this._htmlUtilities = htmlUtilities;
}
ngOnInit(): void {
}
ngOnDestroy(): void {
this.subs.forEach((s) => s.unsubscribe());
}
writeValue(value: string): void {
if (value) {
this.formControl.setValue(value);
}
if (value === null) {
this.formControl.reset();
this.formControl.setValue('');
}
}
registerOnChange(fn: any): void {
this.subs.push(
this.formControl.valueChanges.subscribe(fn)
);
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
validate(_: FormControl) {
return this.formControl.valid ? null : this.formControl.errors;
}
getErrorMessage() {
if (this.formControl.errors['required']) {
return ERROR_MESSAGES.REQUIRED;
}
if (this.formControl.errors['whitespace']) {
return ERROR_MESSAGES.WHITESPACE;
}
}
}
rich-text.component.html
<div>
<kendo-label [text]="label" class="rich-text-label"></kendo-label>
<kendo-editor [formControl]="formControl" (blur)="onTouch()"
[placeholder]="placeholder" [pasteCleanupSettings]="_htmlUtilities.pasteCleanupSettings">
<kendo-toolbar>
<kendo-toolbar-buttongroup>
<kendo-toolbar-button kendoEditorBoldButton></kendo-toolbar-button>
<kendo-toolbar-button kendoEditorItalicButton></kendo-toolbar-button>
<kendo-toolbar-button kendoEditorUnderlineButton></kendo-toolbar-button>
</kendo-toolbar-buttongroup>
<kendo-toolbar-colorpicker
kendoEditorForeColor
[paletteSettings]="paletteSettings"
></kendo-toolbar-colorpicker>
<kendo-toolbar-colorpicker
kendoEditorBackColor
[paletteSettings]="paletteSettings"
></kendo-toolbar-colorpicker>
<kendo-toolbar-buttongroup>
<kendo-toolbar-button
kendoEditorInsertUnorderedListButton
></kendo-toolbar-button>
<kendo-toolbar-button
kendoEditorInsertOrderedListButton
></kendo-toolbar-button>
</kendo-toolbar-buttongroup>
<kendo-toolbar-buttongroup>
<kendo-toolbar-button
kendoEditorCreateLinkButton
></kendo-toolbar-button>
<kendo-toolbar-button kendoEditorUnlinkButton></kendo-toolbar-button>
</kendo-toolbar-buttongroup>
</kendo-toolbar>
</kendo-editor>
<mat-error *ngIf="formControl.invalid">
{{getErrorMessage(formControl) | translate}}
</mat-error>
</div>