Skip to content

Commit c6bc806

Browse files
committed
Merge branch 'master' into dmdimitrov/issue6453-master
2 parents 8d87f36 + 10ddeef commit c6bc806

23 files changed

+741
-840
lines changed

projects/igniteui-angular/src/lib/chips/chips-area.spec.ts

Lines changed: 372 additions & 600 deletions
Large diffs are not rendered by default.

projects/igniteui-angular/src/lib/combo/combo.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
<ng-content select="igx-hint, [igxHint]"></ng-content>
1010
</ng-container>
1111
<input igxInput #comboInput name="comboInput" type="text" [value]="value" readonly [attr.placeholder]="placeholder"
12-
[disabled]="disabled" (blur)="onBlur()" />
12+
[disabled]="disabled" (blur)="onBlur()" (focus)="onFocus()"/>
1313
<ng-container ngProjectAs="igx-suffix">
1414
<ng-content select="igx-suffix"></ng-content>
1515
</ng-container>
16-
<igx-suffix *ngIf="value.length" aria-label="Clear Selection" class="igx-combo__clear-button" igxRipple
16+
<igx-suffix *ngIf="value.length" aria-label="Clear Selection" class="igx-combo__clear-button"
1717
(click)="handleClearItems($event)">
1818
<ng-container *ngIf="clearIconTemplate">
1919
<ng-container *ngTemplateOutlet="clearIconTemplate"></ng-container>

projects/igniteui-angular/src/lib/combo/combo.component.spec.ts

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { IgxToggleModule } from '../directives/toggle/toggle.directive';
66
import { IgxComboItemComponent } from './combo-item.component';
77
import { IgxComboComponent, IgxComboModule, IComboSelectionChangeEventArgs, IgxComboState } from './combo.component';
88
import { IgxComboDropDownComponent } from './combo-dropdown.component';
9-
import { FormGroup, FormControl, Validators, FormBuilder, ReactiveFormsModule, FormsModule } from '@angular/forms';
9+
import { FormGroup, FormControl, Validators, FormBuilder, ReactiveFormsModule, FormsModule, NgControl } from '@angular/forms';
1010
import { IForOfState } from '../directives/for-of/for_of.directive';
1111
import { BehaviorSubject, Observable } from 'rxjs';
1212
import { take } from 'rxjs/operators';
@@ -3250,6 +3250,25 @@ describe('igxCombo', () => {
32503250
fixture.detectChanges();
32513251
expect(component.selectedItems).toEqual([combo.data[0], combo.data[2], combo.data[4]]);
32523252
}));
3253+
3254+
it('Should have correctly bound focus and blur handlers', () => {
3255+
const fixture = TestBed.createComponent(IgxComboInTemplatedFormComponent);
3256+
fixture.detectChanges();
3257+
const combo = fixture.componentInstance.testCombo;
3258+
const input = fixture.debugElement.query(By.css(`${CSS_CLASS_INPUTGROUP} input`));
3259+
3260+
spyOn(combo, 'onFocus');
3261+
spyOn(combo, 'onBlur');
3262+
3263+
3264+
input.triggerEventHandler('focus', {});
3265+
expect(combo.onFocus).toHaveBeenCalled();
3266+
expect(combo.onFocus).toHaveBeenCalledWith();
3267+
3268+
input.triggerEventHandler('blur', {});
3269+
expect(combo.onBlur).toHaveBeenCalled();
3270+
expect(combo.onFocus).toHaveBeenCalledWith();
3271+
});
32533272
});
32543273

32553274
describe('Combo - Display Density', () => {
@@ -3322,6 +3341,66 @@ describe('igxCombo', () => {
33223341
});
33233342
});
33243343

3344+
describe('Combo ControlValueAccessor Unit', () => {
3345+
let combo: IgxComboComponent;
3346+
it('should correctly implement interface methods', () => {
3347+
const mockSelection: {
3348+
[key: string]: jasmine.Spy
3349+
} = jasmine.createSpyObj('IgxSelectionAPIService', ['get', 'set', 'add_items', 'select_items']);
3350+
const mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['markForCheck']);
3351+
const mockComboService = jasmine.createSpyObj('IgxComboAPIService', ['register']);
3352+
const mockNgControl = jasmine.createSpyObj('NgControl', ['registerOnChangeCb', 'registerOnTouchedCb']);
3353+
const mockInjector = jasmine.createSpyObj('Injector', {
3354+
'get': mockNgControl
3355+
});
3356+
mockSelection.get.and.returnValue(new Set([]));
3357+
3358+
// init
3359+
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
3360+
combo.ngOnInit();
3361+
expect(mockInjector.get).toHaveBeenCalledWith(NgControl, null);
3362+
combo.registerOnChange(mockNgControl.registerOnChangeCb);
3363+
combo.registerOnTouched(mockNgControl.registerOnTouchedCb);
3364+
3365+
// writeValue
3366+
expect(combo.value).toBe('');
3367+
mockSelection.add_items.and.returnValue(new Set(['test']));
3368+
spyOnProperty(combo, 'isRemote').and.returnValue(false);
3369+
combo.writeValue(['test']);
3370+
// TODO: Uncomment after fix for write value going through entire selection process
3371+
// expect(mockNgControl.registerOnChangeCb).not.toHaveBeenCalled();
3372+
expect(mockSelection.add_items).toHaveBeenCalledWith(combo.id, ['test'], true);
3373+
expect(mockSelection.select_items).toHaveBeenCalledWith(combo.id, ['test'], true);
3374+
expect(combo.value).toBe('test');
3375+
3376+
// setDisabledState
3377+
combo.setDisabledState(true);
3378+
expect(combo.disabled).toBe(true);
3379+
combo.setDisabledState(false);
3380+
expect(combo.disabled).toBe(false);
3381+
3382+
// OnChange callback
3383+
mockSelection.add_items.and.returnValue(new Set(['simpleValue']));
3384+
combo.selectItems(['simpleValue']);
3385+
expect(mockSelection.add_items).toHaveBeenCalledWith(combo.id, ['simpleValue'], undefined);
3386+
expect(mockSelection.select_items).toHaveBeenCalledWith(combo.id, ['simpleValue'], true);
3387+
expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledWith(['simpleValue']);
3388+
3389+
// OnTouched callback
3390+
spyOnProperty(combo, 'collapsed').and.returnValue(true);
3391+
spyOnProperty(combo, 'valid', 'set');
3392+
3393+
combo.onFocus();
3394+
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(1);
3395+
3396+
combo.onBlur();
3397+
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(2);
3398+
});
3399+
3400+
it('should correctly handle ngControl validity', () => {
3401+
pending('Convert existing form test here');
3402+
});
3403+
});
33253404
@Component({
33263405
template: `
33273406
<igx-combo #combo

projects/igniteui-angular/src/lib/combo/combo.component.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
151151
private _itemsMaxHeight = null;
152152
private _remoteSelection = {};
153153
private _onChangeCallback: (_: any) => void = noop;
154+
private _onTouchedCallback: () => void = noop;
154155
private _overlaySettings: OverlaySettings = {
155156
scrollStrategy: new AbsoluteScrollStrategy(),
156157
positionStrategy: new ConnectedPositioningStrategy(),
@@ -1124,6 +1125,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
11241125
*/
11251126
public onBlur() {
11261127
if (this.collapsed) {
1128+
this._onTouchedCallback();
11271129
if (this.ngControl && !this.ngControl.valid) {
11281130
this.valid = IgxComboState.INVALID;
11291131
} else {
@@ -1132,6 +1134,13 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
11321134
}
11331135
}
11341136

1137+
/** @hidden @internal */
1138+
public onFocus() {
1139+
if (this.collapsed) {
1140+
this._onTouchedCallback();
1141+
}
1142+
}
1143+
11351144
/**
11361145
* @hidden @internal
11371146
*/
@@ -1185,7 +1194,9 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
11851194
/**
11861195
* @hidden @internal
11871196
*/
1188-
public registerOnTouched(fn: any): void { }
1197+
public registerOnTouched(fn: any): void {
1198+
this._onTouchedCallback = fn;
1199+
}
11891200

11901201
/**
11911202
* @hidden @internal
@@ -1229,6 +1240,11 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
12291240
*/
12301241
public handleClearItems(event: Event): void {
12311242
this.deselectAllItems(true, event);
1243+
if (this.collapsed) {
1244+
this.getEditElement().focus();
1245+
} else {
1246+
this.focusSearchInput(true);
1247+
}
12321248
event.stopPropagation();
12331249
}
12341250

projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-component.scss

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,18 @@
2929
@extend %time-picker__item !optional;
3030
}
3131

32-
@include e(item, $mod: selected) {
32+
@include e(item, $m: selected) {
3333
@extend %time-picker__item--selected !optional;
3434
}
3535

3636
@include e(item, $m: active) {
3737
@extend %time-picker__item--active !optional;
3838
}
3939

40+
@include e(item, $m: disabled) {
41+
@extend %time-picker__item--disabled !optional;
42+
}
43+
4044
// HOUR
4145
@include e(hourList) {
4246
@extend %time-picker__hourList !optional;
@@ -77,3 +81,4 @@
7781
}
7882
}
7983
}
84+

projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-theme.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
/// @param {Color} $hover-text-color [null] - The hover text color of a open time picker.
1717
/// @param {Color} $selected-text-color [null] - The text color of a selected item in time picker.
1818
/// @param {Color} $active-item-background [null] - The background color for current item in focused column inside the time picker.
19+
/// @param {Color} $disabled-text-color [null] - The text color for disabled values.
20+
/// @param {Color} $disabled-item-background [null] - The background color for disabled values .
1921
/// @param {Color} $header-background [null] - The header background color of a time picker.
2022
/// @param {Color} $header-hour-text-color [null] - The header hour text color of a time picker.
2123
/// @param {Color} $header-time-period-color [null] - The header AM/PM text color of a time picker.
@@ -52,6 +54,8 @@
5254
$hover-text-color: null,
5355
$selected-text-color: null,
5456
$active-item-background: null,
57+
$disabled-text-color: null,
58+
$disabled-item-background: null,
5559
$header-background: null,
5660
$header-hour-text-color: null,
5761
$header-time-period-color: null,
@@ -102,6 +106,12 @@
102106
}
103107
}
104108

109+
@if not($disabled-text-color) and $disabled-item-background {
110+
@if type-of($disabled-item-background) == 'color' {
111+
$disabled-text-color: rgba(text-contrast($disabled-item-background), .6);
112+
}
113+
}
114+
105115
@if not($modal-shadow) {
106116
$elevation: map-get($time-picker-schema, 'modal-elevation');
107117
$modal-shadow: igx-elevation($elevations, $elevation);
@@ -119,6 +129,8 @@
119129
hover-text-color: $hover-text-color,
120130
selected-text-color: $selected-text-color,
121131
active-item-background: $active-item-background,
132+
disabled-text-color: $disabled-text-color,
133+
disabled-item-background: $disabled-item-background,
122134
header-background: $header-background,
123135
header-hour-text-color: $header-hour-text-color,
124136
header-time-period-color: $header-time-period-color,
@@ -263,6 +275,12 @@
263275
background: --var($theme, 'active-item-background');
264276
}
265277

278+
%time-picker__item--disabled {
279+
color: --var($theme, 'disabled-text-color');
280+
background: --var($theme, 'disabled-item-background');
281+
pointer-events: none;
282+
}
283+
266284
%time-picker__header {
267285
background: --var($theme, 'header-background');
268286
padding: rem(24px) rem(16px);
@@ -334,3 +352,4 @@
334352
}
335353
}
336354
}
355+

projects/igniteui-angular/src/lib/core/styles/themes/schemas/light/_time-picker.scss

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
/// @prop {Map} hover-text-color [igx-color: ('secondary', 500)] - The hover text color of a open time picker.
1515
/// @prop {Map} selected-text-color [igx-color: ('secondary', 500)] - The text color of a selected item in time picker.
1616
/// @prop {Map} active-item-background [igx-color: ('grays', 100)] - The background color for current item in focused column inside the time picker.
17+
/// @prop {Map} disabled-text-color [igx-color: ('grays', 500), hexrgba: (), rgba: .6] - The text color for disabled values.
18+
/// @prop {Map} disabled-item-background [igx-color: ('grays', 100)] - The background color for disabled values .
1719
/// @prop {Map} header-background [igx-color: ('secondary', 500)] - The header background color of a time picker.
1820
/// @prop {Map} header-hour-text-color [igx-contrast-color: ('secondary', 500)] - The header hour text color of a time picker.
1921
/// @prop {Map} header-time-period-color [igx-contrast-color: ('secondary', 500), rgba: .8] - The header AM/PM text color of a time picker.
@@ -47,6 +49,14 @@ $_light-time-picker: extend(
4749
igx-color: ('grays', 100)
4850
),
4951

52+
disabled-text-color: (
53+
igx-color: ('grays', 500),
54+
hexrgba: (),
55+
rgba: .5
56+
),
57+
58+
disabled-item-background: transparent,
59+
5060
header-background: (
5161
igx-color: ('secondary', 500)
5262
),
@@ -74,3 +84,4 @@ $_light-time-picker: extend(
7484
/// @requires $_light-time-picker
7585
/// @requires $_fluent-shape-time-picker
7686
$_fluent-time-picker: extend($_light-time-picker, $_fluent-shape-time-picker);
87+

0 commit comments

Comments
 (0)