Skip to content

Commit b8c464a

Browse files
authored
feat(form-control): support igc-color-picker in CVA (#17587)
1 parent c5f6f3d commit b8c464a

3 files changed

Lines changed: 185 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ All notable changes for each version of this project will be documented in this
66

77
### New Features
88

9+
- `IgcFormControlDirective`
10+
- Added support for `igc-color-picker` so it can be bound with `ngModel` and `formControlName`, in the same way `igc-rating` is already supported.
11+
912
- `IgxChipComponent`
1013
- Added the `outlined` property to the component. When set to `true`, the Chip will have an outlined style.
1114

projects/igniteui-angular/directives/src/directives/form-control/form-control.directive.spec.ts

Lines changed: 181 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Component, DebugElement, ElementRef, Renderer2, ViewChild, ChangeDetectionStrategy } from '@angular/core';
22
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
3-
import { FormsModule } from '@angular/forms';
3+
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
44
import { By } from '@angular/platform-browser';
5-
import { defineComponents, IgcRatingComponent } from 'igniteui-webcomponents';
5+
import { defineComponents, IgcColorPickerComponent, IgcRatingComponent } from 'igniteui-webcomponents';
66

77
import { IgcFormControlDirective } from './form-control.directive';
88

@@ -12,6 +12,7 @@ describe('IgcFormControlDirective - ', () => {
1212
let directive: IgcFormControlDirective;
1313
let input: DebugElement;
1414
let rating: IgcRatingComponent;
15+
let colorPicker: IgcColorPickerComponent;
1516

1617
describe('Unit tests: ', () => {
1718

@@ -67,6 +68,56 @@ describe('IgcFormControlDirective - ', () => {
6768
});
6869
});
6970

71+
describe('Unit tests - igc-color-picker: ', () => {
72+
73+
beforeEach(waitForAsync(() => {
74+
defineComponents(IgcColorPickerComponent);
75+
76+
TestBed.configureTestingModule({
77+
providers: [
78+
{ provide: ElementRef, useValue: colorPickerElementRef },
79+
{ provide: Renderer2, useValue: renderer2Mock },
80+
IgcFormControlDirective
81+
]
82+
});
83+
}));
84+
85+
const colorPickerElementRef = { nativeElement: document.createElement('igc-color-picker') };
86+
87+
const mockNgControl = jasmine.createSpyObj('NgControl', [
88+
'registerOnChangeCb',
89+
'registerOnTouchedCb'
90+
]);
91+
92+
const renderer2Mock = jasmine.createSpyObj('renderer2Mock', [
93+
'setProperty'
94+
]);
95+
96+
it('should correctly implement interface methods - ControlValueAccessor ', () => {
97+
directive = TestBed.inject(IgcFormControlDirective);
98+
directive.registerOnChange(mockNgControl.registerOnChangeCb);
99+
directive.registerOnTouched(mockNgControl.registerOnTouchedCb);
100+
101+
// value setter
102+
expect(colorPickerElementRef.nativeElement.value).toBeUndefined();
103+
directive.writeValue('#ff0000');
104+
expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledTimes(0);
105+
expect(colorPickerElementRef.nativeElement.value).toBe('#ff0000');
106+
107+
// listening for value change
108+
directive.listenForValueChange('#00ff00');
109+
expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledWith('#00ff00');
110+
111+
// setDisabledState
112+
directive.setDisabledState(true);
113+
expect(renderer2Mock.setProperty).toHaveBeenCalledWith(colorPickerElementRef.nativeElement, 'disabled', true);
114+
115+
// OnTouched callback
116+
directive.onBlur();
117+
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(1);
118+
});
119+
});
120+
70121
describe('ngModel two-way binding tests: ', () => {
71122
beforeEach(waitForAsync(() => {
72123
TestBed.configureTestingModule({
@@ -109,6 +160,95 @@ describe('IgcFormControlDirective - ', () => {
109160
expect(input.nativeElement.value).toEqual('8');
110161
});
111162
});
163+
164+
describe('ngModel two-way binding tests - igc-color-picker: ', () => {
165+
beforeEach(waitForAsync(() => {
166+
TestBed.configureTestingModule({
167+
imports: [
168+
IgxFormsColorPickerControlComponent
169+
]
170+
}).compileComponents();
171+
defineComponents(IgcColorPickerComponent);
172+
}));
173+
174+
beforeEach(fakeAsync(() => {
175+
fixture = TestBed.createComponent(IgxFormsColorPickerControlComponent);
176+
fixture.detectChanges();
177+
input = fixture.debugElement.query(By.css(`#basicModelColor`));
178+
colorPicker = fixture.debugElement.query(By.directive(IgcFormControlDirective)).nativeElement;
179+
tick();
180+
fixture.detectChanges();
181+
}));
182+
183+
it('Should properly init for igc-color-picker.', () => {
184+
directive = fixture.componentInstance.directive;
185+
expect(directive).toBeTruthy();
186+
});
187+
188+
it('Should reflect ngModel change to color-picker', async () => {
189+
input.nativeElement.value = '#ff0000';
190+
input.nativeElement.dispatchEvent(new Event('input'));
191+
fixture.detectChanges();
192+
await fixture.whenStable();
193+
fixture.detectChanges();
194+
expect(colorPicker.value).toEqual('#ff0000');
195+
});
196+
197+
it('Should reflect ngModel change from color-picker', async () => {
198+
colorPicker.setAttribute('value', '#00ff00');
199+
colorPicker.dispatchEvent(new CustomEvent('igcChange', { detail: '#00ff00' }));
200+
fixture.detectChanges();
201+
await fixture.whenStable();
202+
fixture.detectChanges();
203+
expect(input.nativeElement.value).toEqual('#00ff00');
204+
});
205+
});
206+
207+
describe('Reactive forms tests - igc-color-picker: ', () => {
208+
beforeEach(waitForAsync(() => {
209+
TestBed.configureTestingModule({
210+
imports: [
211+
IgxReactiveFormsColorPickerControlComponent
212+
]
213+
}).compileComponents();
214+
defineComponents(IgcColorPickerComponent);
215+
}));
216+
217+
beforeEach(fakeAsync(() => {
218+
fixture = TestBed.createComponent(IgxReactiveFormsColorPickerControlComponent);
219+
fixture.detectChanges();
220+
colorPicker = fixture.debugElement.query(By.directive(IgcFormControlDirective)).nativeElement;
221+
tick();
222+
fixture.detectChanges();
223+
}));
224+
225+
it('Should write the initial FormControl value to the color-picker', () => {
226+
expect(colorPicker.value).toEqual('#ff0000');
227+
});
228+
229+
it('Should update the FormControl value when the color-picker emits igcChange', async () => {
230+
colorPicker.setAttribute('value', '#0000ff');
231+
colorPicker.dispatchEvent(new CustomEvent('igcChange', { detail: '#0000ff' }));
232+
fixture.detectChanges();
233+
await fixture.whenStable();
234+
fixture.detectChanges();
235+
expect(fixture.componentInstance.form.get('color').value).toEqual('#0000ff');
236+
});
237+
238+
it('Should mark the FormControl as touched on blur', () => {
239+
expect(fixture.componentInstance.form.get('color').touched).toBeFalse();
240+
colorPicker.dispatchEvent(new Event('blur'));
241+
fixture.detectChanges();
242+
expect(fixture.componentInstance.form.get('color').touched).toBeTrue();
243+
});
244+
245+
it('Should reflect FormControl disabled state to the color-picker', () => {
246+
expect(colorPicker.disabled).toBeFalse();
247+
fixture.componentInstance.form.get('color').disable();
248+
fixture.detectChanges();
249+
expect(colorPicker.disabled).toBeTrue();
250+
});
251+
});
112252
});
113253

114254
@Component({
@@ -132,3 +272,42 @@ class IgxFormsControlComponent {
132272
};
133273
}
134274

275+
@Component({
276+
template: `
277+
<form #form2="ngForm">
278+
<input type="text" id="basicModelColor" name="model color" [(ngModel)]="model.Color">
279+
<igc-color-picker name="modelColor" [(ngModel)]="model.Color" label="Model Color"></igc-color-picker>
280+
</form>
281+
`,
282+
changeDetection: ChangeDetectionStrategy.Eager,
283+
imports: [IgcFormControlDirective, FormsModule]
284+
})
285+
class IgxFormsColorPickerControlComponent {
286+
287+
@ViewChild(IgcFormControlDirective, { static: true })
288+
public directive: IgcFormControlDirective;
289+
290+
public model = {
291+
Color: '#000000'
292+
};
293+
}
294+
295+
@Component({
296+
template: `
297+
<form [formGroup]="form">
298+
<igc-color-picker formControlName="color" label="Reactive Color"></igc-color-picker>
299+
</form>
300+
`,
301+
changeDetection: ChangeDetectionStrategy.Eager,
302+
imports: [IgcFormControlDirective, ReactiveFormsModule]
303+
})
304+
class IgxReactiveFormsColorPickerControlComponent {
305+
306+
@ViewChild(IgcFormControlDirective, { static: true })
307+
public directive: IgcFormControlDirective;
308+
309+
public form = new FormGroup({
310+
color: new FormControl('#ff0000')
311+
});
312+
}
313+

projects/igniteui-angular/directives/src/directives/form-control/form-control.directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
33

44
@Directive({
55
// eslint-disable-next-line @angular-eslint/directive-selector
6-
selector: 'igc-rating[ngModel],igc-rating[formControlName]',
6+
selector: 'igc-rating[ngModel],igc-rating[formControlName],igc-color-picker[ngModel],igc-color-picker[formControlName]',
77
providers: [
88
{
99
provide: NG_VALUE_ACCESSOR,

0 commit comments

Comments
 (0)