From 9e18a1688d8b0cdcbc95c3110105355d00dbfa1f Mon Sep 17 00:00:00 2001
From: Erika McVey <50454925+Blackbaud-ErikaMcVey@users.noreply.github.com>
Date: Wed, 7 Feb 2024 09:31:16 -0500
Subject: [PATCH 1/3] feat(components/colorpicker): add form errors to
colorpicker
---
.../colorpicker/basic/demo.component.html | 5 ++
.../colorpicker/basic/demo.component.ts | 20 ++++-
.../colorpicker/colorpicker.component.html | 21 +++++
.../colorpicker/colorpicker.component.ts | 15 +++-
.../colorpicker-input.directive.ts | 23 +++++-
.../colorpicker/colorpicker-input.service.ts | 3 +
.../colorpicker/colorpicker.component.html | 11 +++
.../colorpicker/colorpicker.component.spec.ts | 80 +++++++++++++++++--
.../colorpicker/colorpicker.component.ts | 57 ++++++++++++-
.../modules/colorpicker/colorpicker.module.ts | 14 +++-
...olorpicker-reactive-component.fixture.html | 23 ++++++
.../colorpicker-reactive-component.fixture.ts | 30 ++++++-
12 files changed, 283 insertions(+), 19 deletions(-)
diff --git a/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.html b/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.html
index 16f4fb3f9d..cb8a58bed8 100644
--- a/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.html
+++ b/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.html
@@ -11,6 +11,11 @@
[presetColors]="swatches"
[skyColorpickerInput]="colorPicker"
/>
+
diff --git a/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.ts b/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.ts
index 2be6ed63c9..6bc572ebf1 100644
--- a/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.ts
+++ b/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.ts
@@ -1,9 +1,12 @@
+import { CommonModule } from '@angular/common';
import { Component, inject } from '@angular/core';
import {
+ AbstractControl,
FormBuilder,
- FormControl,
FormGroup,
ReactiveFormsModule,
+ UntypedFormControl,
+ ValidationErrors,
} from '@angular/forms';
import { SkyColorpickerModule, SkyColorpickerOutput } from '@skyux/colorpicker';
@@ -11,10 +14,11 @@ import { SkyColorpickerModule, SkyColorpickerOutput } from '@skyux/colorpicker';
standalone: true,
selector: 'app-demo',
templateUrl: './demo.component.html',
- imports: [ReactiveFormsModule, SkyColorpickerModule],
+ imports: [CommonModule, ReactiveFormsModule, SkyColorpickerModule],
})
export class DemoComponent {
protected formGroup: FormGroup;
+ protected favoriteColor: UntypedFormControl;
protected swatches: string[] = [
'#BD4040',
@@ -26,8 +30,18 @@ export class DemoComponent {
];
constructor() {
+ this.favoriteColor = new UntypedFormControl('#f00', [
+ (control: AbstractControl): ValidationErrors | null => {
+ if (control.value?.rgba?.alpha < 0.8) {
+ return { opaque: true };
+ }
+
+ return null;
+ },
+ ]);
+
this.formGroup = inject(FormBuilder).group({
- favoriteColor: new FormControl('#f00'),
+ favoriteColor: this.favoriteColor,
});
}
diff --git a/apps/playground/src/app/components/colorpicker/colorpicker/colorpicker.component.html b/apps/playground/src/app/components/colorpicker/colorpicker/colorpicker.component.html
index 53271e1fed..1a77020fd3 100644
--- a/apps/playground/src/app/components/colorpicker/colorpicker/colorpicker.component.html
+++ b/apps/playground/src/app/components/colorpicker/colorpicker/colorpicker.component.html
@@ -13,8 +13,29 @@
[presetColors]="swatches"
[skyColorpickerInput]="colorPicker"
/>
+
+
+
+
+ Touched |
+ {{ favoriteColor.touched }} |
+
+
+ Pristine |
+ {{ favoriteColor.pristine }} |
+
+
+ Valid |
+ {{ favoriteColor.valid }} |
+
+
+
diff --git a/apps/playground/src/app/components/colorpicker/colorpicker/colorpicker.component.ts b/apps/playground/src/app/components/colorpicker/colorpicker/colorpicker.component.ts
index 8a75549297..c537e4dae8 100644
--- a/apps/playground/src/app/components/colorpicker/colorpicker/colorpicker.component.ts
+++ b/apps/playground/src/app/components/colorpicker/colorpicker/colorpicker.component.ts
@@ -1,8 +1,10 @@
import { Component } from '@angular/core';
import {
+ AbstractControl,
UntypedFormBuilder,
UntypedFormControl,
UntypedFormGroup,
+ ValidationErrors,
} from '@angular/forms';
import { SkyColorpickerOutput } from '@skyux/colorpicker';
@@ -12,6 +14,7 @@ import { SkyColorpickerOutput } from '@skyux/colorpicker';
})
export class ColorpickerComponent {
public reactiveForm: UntypedFormGroup;
+ public favoriteColor: UntypedFormControl;
public swatches: string[] = [
'#BD4040',
@@ -23,8 +26,18 @@ export class ColorpickerComponent {
];
constructor(formBuilder: UntypedFormBuilder) {
+ this.favoriteColor = new UntypedFormControl('#f00', [
+ (control: AbstractControl): ValidationErrors | null => {
+ if (control.value?.rgba?.alpha < 0.8) {
+ return { opaque: true };
+ }
+
+ return null;
+ },
+ ]);
+
this.reactiveForm = formBuilder.group({
- favoriteColor: new UntypedFormControl('#f00'),
+ favoriteColor: this.favoriteColor,
});
}
diff --git a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.directive.ts b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.directive.ts
index f7eb9008d7..25692df39e 100644
--- a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.directive.ts
+++ b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.directive.ts
@@ -22,7 +22,7 @@ import {
} from '@angular/forms';
import { SkyLibResourcesService } from '@skyux/i18n';
-import { Subject, Subscription, takeUntil } from 'rxjs';
+import { Subject, Subscription, distinctUntilChanged, takeUntil } from 'rxjs';
import { SkyColorpickerInputService } from './colorpicker-input.service';
import { SkyColorpickerComponent } from './colorpicker.component';
@@ -223,6 +223,27 @@ export class SkyColorpickerInputDirective
}
});
+ this.#colorpickerInputSvc.ariaError
+ .pipe(
+ distinctUntilChanged((a, b) => {
+ return a.hasError === b.hasError && a.errorId === b.errorId;
+ }),
+ takeUntil(this.#ngUnsubscribe),
+ )
+ .subscribe((errorState) => {
+ if (errorState.hasError) {
+ this.#renderer.setAttribute(element, 'aria-invalid', 'true');
+ this.#renderer.setAttribute(
+ element,
+ 'aria-errormessage',
+ errorState.errorId,
+ );
+ } else {
+ this.#renderer.removeAttribute(element, 'aria-invalid');
+ this.#renderer.removeAttribute(element, 'aria-errormessage');
+ }
+ });
+
this.skyColorpickerInput.updatePickerValues(this.initialColor);
/* Sanity check */
diff --git a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.service.ts b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.service.ts
index 5a6c21baf8..233f147155 100644
--- a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.service.ts
+++ b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.service.ts
@@ -9,4 +9,7 @@ import { ReplaySubject } from 'rxjs';
export class SkyColorpickerInputService {
public inputId = new ReplaySubject(1);
public labelText = new ReplaySubject(1);
+ public ariaError = new ReplaySubject<{ hasError: boolean; errorId: string }>(
+ 1,
+ );
}
diff --git a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.html b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.html
index 335b1fe234..f7f08f4126 100644
--- a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.html
+++ b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.html
@@ -323,3 +323,14 @@
+
+
+
+
+
+
diff --git a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.spec.ts b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.spec.ts
index 20ca8bd882..b36baab140 100644
--- a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.spec.ts
+++ b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.spec.ts
@@ -41,14 +41,16 @@ describe('Colorpicker Component', () => {
return document.querySelector('.sky-colorpicker-container') as HTMLElement;
}
- function openColorpicker(element: HTMLElement): void {
+ function openColorpicker(element: HTMLElement, className?: string): void {
tick();
fixture.detectChanges();
verifyMenuVisibility(false);
- const buttonElem = element.querySelector(
- '.sky-colorpicker-button',
- ) as HTMLElement;
+ const buttonSelector = className
+ ? `.${className} .sky-colorpicker-button`
+ : '.sky-colorpicker-button';
+ const buttonElem = element.querySelector(buttonSelector) as HTMLElement;
+
buttonElem.click();
tick();
fixture.detectChanges();
@@ -1210,20 +1212,21 @@ describe('Colorpicker Component', () => {
verifyColorpicker(nativeElement, 'rgba(40,137,229,1)', '40, 137, 229');
}));
- it('should toggle reset button via messageStream.', fakeAsync(() => {
+ it('should toggle reset button via messageStream', fakeAsync(() => {
fixture.detectChanges();
tick();
- expect(getResetButton().length).toEqual(1);
+ expect(getResetButton().length).toEqual(2);
component.sendMessage(SkyColorpickerMessageType.ToggleResetButton);
tick();
fixture.detectChanges();
tick();
- expect(getResetButton().length).toEqual(0);
+ // There are 2 colorpicker components and only one is using the message stream
+ expect(getResetButton().length).toEqual(1);
component.sendMessage(SkyColorpickerMessageType.ToggleResetButton);
tick();
fixture.detectChanges();
tick();
- expect(getResetButton().length).toEqual(1);
+ expect(getResetButton().length).toEqual(2);
}));
it('should only emit the form control valueChanged event once per change', (done) => {
@@ -1318,6 +1321,67 @@ describe('Colorpicker Component', () => {
expect(outermostDiv).not.toHaveCssClass('sky-colorpicker-disabled');
});
+
+ it('should render an error message if the form control set via name has an error', fakeAsync(() => {
+ component.labelText = 'Label Text';
+
+ fixture.detectChanges();
+
+ let inputElement: HTMLInputElement | null =
+ nativeElement.querySelector('input');
+
+ expect(inputElement?.getAttribute('aria-invalid')).toBeNull();
+ expect(inputElement?.getAttribute('aria-errormessage')).toBeNull();
+
+ openColorpicker(nativeElement);
+ setInputElementValue(nativeElement, 'red', '163');
+ setInputElementValue(nativeElement, 'green', '19');
+ setInputElementValue(nativeElement, 'blue', '84');
+ setInputElementValue(nativeElement, 'alpha', '0.5');
+ applyColorpicker();
+
+ fixture.detectChanges();
+
+ inputElement = nativeElement.querySelector('input');
+
+ expect(inputElement?.getAttribute('aria-invalid')).toBe('true');
+ expect(inputElement?.getAttribute('aria-errormessage')).toBeDefined();
+
+ const errorMessage = nativeElement.querySelector('sky-form-error');
+
+ expect(errorMessage).toBeVisible();
+ }));
+
+ it('should render an error message if the form control has an error set via form control', fakeAsync(() => {
+ fixture.detectChanges();
+
+ let inputElement: HTMLInputElement | null = nativeElement.querySelector(
+ '.colorpicker-form-control input',
+ );
+
+ expect(inputElement?.getAttribute('aria-invalid')).toBeNull();
+ expect(inputElement?.getAttribute('aria-errormessage')).toBeNull();
+
+ openColorpicker(nativeElement, 'colorpicker-form-control');
+ setInputElementValue(nativeElement, 'red', '163');
+ setInputElementValue(nativeElement, 'green', '19');
+ setInputElementValue(nativeElement, 'blue', '84');
+ setInputElementValue(nativeElement, 'alpha', '0.5');
+ applyColorpicker();
+
+ fixture.detectChanges();
+
+ inputElement = nativeElement.querySelector(
+ '.colorpicker-form-control input',
+ );
+
+ expect(inputElement?.getAttribute('aria-invalid')).toBe('true');
+ expect(inputElement?.getAttribute('aria-errormessage')).toBeDefined();
+
+ const errorMessage = nativeElement.querySelector('sky-form-error');
+
+ expect(errorMessage).toBeVisible();
+ }));
});
describe('accessibility', () => {
diff --git a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.ts b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.ts
index 428737771a..173f3b48e4 100644
--- a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.ts
+++ b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.ts
@@ -1,6 +1,8 @@
import {
+ AfterContentChecked,
ChangeDetectorRef,
Component,
+ ContentChild,
ElementRef,
EnvironmentInjector,
EventEmitter,
@@ -14,6 +16,12 @@ import {
ViewEncapsulation,
inject,
} from '@angular/core';
+import {
+ AbstractControlDirective,
+ FormControlDirective,
+ FormControlName,
+ NgModel,
+} from '@angular/forms';
import {
SkyAffixAutoFitContext,
SkyAffixService,
@@ -23,6 +31,7 @@ import {
SkyOverlayInstance,
SkyOverlayService,
} from '@skyux/core';
+import { SKY_FORM_ERRORS_ENABLED } from '@skyux/forms';
import { SkyIconType } from '@skyux/indicators';
import { SkyThemeService } from '@skyux/theme';
@@ -52,10 +61,16 @@ let componentIdIndex = 0;
selector: 'sky-colorpicker',
templateUrl: './colorpicker.component.html',
styleUrls: ['./colorpicker.component.scss'],
- providers: [SkyColorpickerInputService, SkyColorpickerService],
+ providers: [
+ SkyColorpickerInputService,
+ SkyColorpickerService,
+ { provide: SKY_FORM_ERRORS_ENABLED, useValue: true },
+ ],
encapsulation: ViewEncapsulation.None,
})
-export class SkyColorpickerComponent implements OnInit, OnDestroy {
+export class SkyColorpickerComponent
+ implements OnInit, OnDestroy, AfterContentChecked
+{
/**
* The name of the [Font Awesome 4.7](https://fontawesome.com/v4.7/icons/) icon to overlay on top of the picker. Do not specify the `fa fa-` classes.
* @internal
@@ -281,6 +296,30 @@ export class SkyColorpickerComponent implements OnInit, OnDestroy {
return this.#_colorpickerRef;
}
+ @ContentChild(FormControlDirective)
+ protected set formControl(value: FormControlDirective | undefined) {
+ if (value) {
+ this.ngControl = value;
+ this.#changeDetector.markForCheck();
+ }
+ }
+
+ @ContentChild(FormControlName)
+ protected set formControlByName(value: FormControlName | undefined) {
+ if (value) {
+ this.ngControl = value;
+ this.#changeDetector.markForCheck();
+ }
+ }
+
+ @ContentChild(NgModel)
+ protected set ngModel(value: NgModel | undefined) {
+ if (value) {
+ this.ngControl = value;
+ this.#changeDetector.markForCheck();
+ }
+ }
+
protected inputId: string | undefined;
protected colorpickerId: string;
protected isOpen = false;
@@ -299,6 +338,7 @@ export class SkyColorpickerComponent implements OnInit, OnDestroy {
protected selectedColor: SkyColorpickerOutput | undefined;
protected iconColor: string | undefined;
protected isPickerVisible: boolean | undefined;
+ protected ngControl: AbstractControlDirective | undefined;
#idIndex: number;
#alphaChannel: string | undefined;
@@ -322,6 +362,8 @@ export class SkyColorpickerComponent implements OnInit, OnDestroy {
readonly #colorpickerInputSvc = inject(SkyColorpickerInputService);
readonly #idSvc = inject(SkyIdService);
+ protected readonly errorId = this.#idSvc.generateId();
+
#_backgroundColorForDisplay: string | undefined;
#_colorpickerRef: ElementRef | undefined;
#_disabled = false;
@@ -411,6 +453,15 @@ export class SkyColorpickerComponent implements OnInit, OnDestroy {
}
}
+ public ngAfterContentChecked(): void {
+ if (this.labelText) {
+ this.#colorpickerInputSvc.ariaError.next({
+ hasError: !this.ngControl?.valid,
+ errorId: this.errorId,
+ });
+ }
+ }
+
public ngOnDestroy(): void {
this.#ngUnsubscribe.next();
this.#ngUnsubscribe.complete();
@@ -420,6 +471,8 @@ export class SkyColorpickerComponent implements OnInit, OnDestroy {
}
public onTriggerButtonClick(): void {
+ this.ngControl?.control?.markAsTouched();
+
this.#sendMessage(SkyColorpickerMessageType.Open);
}
diff --git a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.module.ts b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.module.ts
index 9caa3816a7..7c87e666b4 100644
--- a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.module.ts
+++ b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.module.ts
@@ -1,7 +1,11 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { SkyAffixModule } from '@skyux/core';
-import { SkyInputBoxModule } from '@skyux/forms';
+import {
+ SkyFormErrorModule,
+ SkyFormErrorsModule,
+ SkyInputBoxModule,
+} from '@skyux/forms';
import { SkyIconModule } from '@skyux/indicators';
import { SkyThemeModule } from '@skyux/theme';
@@ -23,10 +27,16 @@ import { SkyColorpickerComponent } from './colorpicker.component';
CommonModule,
SkyAffixModule,
SkyColorpickerResourcesModule,
+ SkyFormErrorModule,
+ SkyFormErrorsModule,
SkyIconModule,
SkyInputBoxModule,
SkyThemeModule,
],
- exports: [SkyColorpickerComponent, SkyColorpickerInputDirective],
+ exports: [
+ SkyColorpickerComponent,
+ SkyColorpickerInputDirective,
+ SkyFormErrorModule,
+ ],
})
export class SkyColorpickerModule {}
diff --git a/libs/components/colorpicker/src/lib/modules/colorpicker/fixtures/colorpicker-reactive-component.fixture.html b/libs/components/colorpicker/src/lib/modules/colorpicker/fixtures/colorpicker-reactive-component.fixture.html
index 78f54098f5..239eea9202 100644
--- a/libs/components/colorpicker/src/lib/modules/colorpicker/fixtures/colorpicker-reactive-component.fixture.html
+++ b/libs/components/colorpicker/src/lib/modules/colorpicker/fixtures/colorpicker-reactive-component.fixture.html
@@ -13,5 +13,28 @@
[outputFormat]="selectedOutputFormat"
[alphaChannel]="selectedHexType"
/>
+
+
+
+
+
+
+
diff --git a/libs/components/colorpicker/src/lib/modules/colorpicker/fixtures/colorpicker-reactive-component.fixture.ts b/libs/components/colorpicker/src/lib/modules/colorpicker/fixtures/colorpicker-reactive-component.fixture.ts
index 428a90a61f..a3421100b0 100644
--- a/libs/components/colorpicker/src/lib/modules/colorpicker/fixtures/colorpicker-reactive-component.fixture.ts
+++ b/libs/components/colorpicker/src/lib/modules/colorpicker/fixtures/colorpicker-reactive-component.fixture.ts
@@ -1,5 +1,10 @@
import { Component, ViewChild } from '@angular/core';
-import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
+import {
+ AbstractControl,
+ UntypedFormControl,
+ UntypedFormGroup,
+ ValidationErrors,
+} from '@angular/forms';
import { Subject } from 'rxjs';
@@ -40,11 +45,32 @@ export class ColorpickerReactiveTestComponent {
public newValues = {
colorModel: '#000',
+ colorModel2: '#000',
};
- public colorControl = new UntypedFormControl('#00f');
+ public colorControl = new UntypedFormControl('#00f', [
+ (control: AbstractControl): ValidationErrors | null => {
+ if (control.value?.rgba?.alpha < 0.8) {
+ return { opaque: true };
+ }
+
+ return null;
+ },
+ ]);
+
+ public colorControl2 = new UntypedFormControl('#00f', [
+ (control: AbstractControl): ValidationErrors | null => {
+ if (control.value?.rgba?.alpha < 0.8) {
+ return { opaque: true };
+ }
+
+ return null;
+ },
+ ]);
+
public colorForm = new UntypedFormGroup({
colorModel: this.colorControl,
+ colorModel2: this.colorControl2,
});
public sendMessage(type: SkyColorpickerMessageType) {
From 688905a5b8171ce8347c3b4b95c3c04b6bed8ed0 Mon Sep 17 00:00:00 2001
From: Erika McVey <50454925+Blackbaud-ErikaMcVey@users.noreply.github.com>
Date: Thu, 8 Feb 2024 08:58:21 -0500
Subject: [PATCH 2/3] address PR feedback
---
.../colorpicker/basic/demo.component.ts | 6 +++---
.../colorpicker/colorpicker.component.html | 19 +++++++++----------
2 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.ts b/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.ts
index 6bc572ebf1..1847d4b646 100644
--- a/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.ts
+++ b/apps/code-examples/src/app/code-examples/colorpicker/colorpicker/basic/demo.component.ts
@@ -3,9 +3,9 @@ import { Component, inject } from '@angular/core';
import {
AbstractControl,
FormBuilder,
+ FormControl,
FormGroup,
ReactiveFormsModule,
- UntypedFormControl,
ValidationErrors,
} from '@angular/forms';
import { SkyColorpickerModule, SkyColorpickerOutput } from '@skyux/colorpicker';
@@ -18,7 +18,7 @@ import { SkyColorpickerModule, SkyColorpickerOutput } from '@skyux/colorpicker';
})
export class DemoComponent {
protected formGroup: FormGroup;
- protected favoriteColor: UntypedFormControl;
+ protected favoriteColor: FormControl;
protected swatches: string[] = [
'#BD4040',
@@ -30,7 +30,7 @@ export class DemoComponent {
];
constructor() {
- this.favoriteColor = new UntypedFormControl('#f00', [
+ this.favoriteColor = new FormControl('#f00', [
(control: AbstractControl): ValidationErrors | null => {
if (control.value?.rgba?.alpha < 0.8) {
return { opaque: true };
diff --git a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.html b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.html
index f7f08f4126..280338d3eb 100644
--- a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.html
+++ b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker.component.html
@@ -324,13 +324,12 @@
-
-
-
-
-
+
+
+
From f580023296c4f9f8dade18abfb3f359e2672ad4a Mon Sep 17 00:00:00 2001
From: Erika McVey <50454925+Blackbaud-ErikaMcVey@users.noreply.github.com>
Date: Thu, 8 Feb 2024 11:13:24 -0500
Subject: [PATCH 3/3] complete subject in ngOnDestroy
---
.../modules/colorpicker/colorpicker-input.service.ts | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.service.ts b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.service.ts
index 233f147155..4c2647ee40 100644
--- a/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.service.ts
+++ b/libs/components/colorpicker/src/lib/modules/colorpicker/colorpicker-input.service.ts
@@ -1,4 +1,4 @@
-import { Injectable } from '@angular/core';
+import { Injectable, OnDestroy } from '@angular/core';
import { ReplaySubject } from 'rxjs';
@@ -6,10 +6,16 @@ import { ReplaySubject } from 'rxjs';
* @internal
*/
@Injectable()
-export class SkyColorpickerInputService {
+export class SkyColorpickerInputService implements OnDestroy {
public inputId = new ReplaySubject(1);
public labelText = new ReplaySubject(1);
public ariaError = new ReplaySubject<{ hasError: boolean; errorId: string }>(
1,
);
+
+ public ngOnDestroy(): void {
+ this.inputId.complete();
+ this.labelText.complete();
+ this.ariaError.complete();
+ }
}