Skip to content

Commit 4ab0467

Browse files
authored
Merge branch '8.1.x' into dpetev/select-control-touched-8.1
2 parents 3b88632 + a4745d1 commit 4ab0467

File tree

5 files changed

+100
-10
lines changed

5 files changed

+100
-10
lines changed

.travis.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
sudo: required
22
dist: xenial
33
addons:
4-
apt:
5-
sources:
6-
- google-chrome
7-
packages:
8-
- google-chrome-stable
4+
chrome: stable
95
services:
106
- xvfb
117
language: node_js

projects/igniteui-angular/karma.conf.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ module.exports = function (config) {
3838
colors: true,
3939
logLevel: config.LOG_INFO,
4040
autoWatch: true,
41-
browsers: ['Chrome'],
41+
browsers: ['ChromeHeadless'],
4242
singleRun: false
4343
});
4444
};

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
<ng-content select="igx-hint, [igxHint]"></ng-content>
2626
</ng-container>
2727
<input igxInput #comboInput name="comboInput" type="text" [value]="value" readonly [attr.placeholder]="placeholder"
28-
[disabled]="disabled" (blur)="onBlur()" />
28+
[disabled]="disabled" (blur)="onBlur()" (focus)="onFocus()"/>
2929
<ng-container ngProjectAs="igx-suffix">
3030
<ng-content select="igx-suffix"></ng-content>
3131
</ng-container>
32-
<igx-suffix *ngIf="value.length" aria-label="Clear Selection" class="igx-combo__clear-button" igxRipple (click)="handleClearItems($event)">
32+
<igx-suffix *ngIf="value.length" aria-label="Clear Selection" class="igx-combo__clear-button" (click)="handleClearItems($event)">
3333
<ng-container *ngIf="clearIconTemplate">
3434
<ng-container *ngTemplateOutlet="clearIconTemplate"></ng-container>
3535
</ng-container>

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

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { IgxToggleModule } from '../directives/toggle/toggle.directive';
77
import { IgxComboItemComponent } from './combo-item.component';
88
import { IgxComboComponent, IgxComboModule, IgxComboState, IComboSelectionChangeEventArgs } from './combo.component';
99
import { IgxComboDropDownComponent } from './combo-dropdown.component';
10-
import { FormGroup, FormControl, Validators, FormBuilder, ReactiveFormsModule, FormsModule } from '@angular/forms';
10+
import { FormGroup, FormControl, Validators, FormBuilder, ReactiveFormsModule, FormsModule, NgControl } from '@angular/forms';
1111
import { IForOfState } from '../directives/for-of/for_of.directive';
1212
import { BehaviorSubject, Observable } from 'rxjs';
1313
import { take } from 'rxjs/operators';
@@ -3196,6 +3196,25 @@ describe('igxCombo', () => {
31963196
fixture.detectChanges();
31973197
expect(fixture.componentInstance.comboSelectedItems).toEqual([...data].splice(1, 3));
31983198
}));
3199+
3200+
it('Should have correctly bound focus and blur handlers', () => {
3201+
const fixture = TestBed.createComponent(SimpleBindComboComponent);
3202+
fixture.detectChanges();
3203+
const combo = fixture.componentInstance.combo;
3204+
const input = fixture.debugElement.query(By.css(`${CSS_CLASS_INPUTGROUP} input`));
3205+
3206+
spyOn(combo, 'onFocus');
3207+
spyOn(combo, 'onBlur');
3208+
3209+
3210+
input.triggerEventHandler('focus', {});
3211+
expect(combo.onFocus).toHaveBeenCalled();
3212+
expect(combo.onFocus).toHaveBeenCalledWith();
3213+
3214+
input.triggerEventHandler('blur', {});
3215+
expect(combo.onBlur).toHaveBeenCalled();
3216+
expect(combo.onFocus).toHaveBeenCalledWith();
3217+
});
31993218
});
32003219

32013220
describe('Combo - Display Density', () => {
@@ -3268,6 +3287,65 @@ describe('igxCombo', () => {
32683287
});
32693288
});
32703289

3290+
describe('Combo ControlValueAccessor Unit', () => {
3291+
let combo: IgxComboComponent;
3292+
it('should correctly implement interface methods', () => {
3293+
const mockSelection: {
3294+
[key: string]: jasmine.Spy
3295+
} = jasmine.createSpyObj('IgxSelectionAPIService', ['get', 'set', 'add_items', 'select_items']);
3296+
const mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['markForCheck']);
3297+
const mockComboService = jasmine.createSpyObj('IgxComboAPIService', ['register']);
3298+
const mockNgControl = jasmine.createSpyObj('NgControl', ['registerOnChangeCb', 'registerOnTouchedCb']);
3299+
const mockInjector = jasmine.createSpyObj('Injector', {
3300+
'get': mockNgControl
3301+
});
3302+
mockSelection.get.and.returnValue(new Set([]));
3303+
3304+
// init
3305+
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
3306+
combo.ngOnInit();
3307+
expect(mockInjector.get).toHaveBeenCalledWith(NgControl, null);
3308+
combo.registerOnChange(mockNgControl.registerOnChangeCb);
3309+
combo.registerOnTouched(mockNgControl.registerOnTouchedCb);
3310+
3311+
// writeValue
3312+
expect(combo.value).toBe('');
3313+
mockSelection.add_items.and.returnValue(new Set(['test']));
3314+
spyOnProperty(combo, 'isRemote').and.returnValue(false);
3315+
combo.writeValue(['test']);
3316+
// TODO: Uncomment after fix for write value going through entire selection process
3317+
// expect(mockNgControl.registerOnChangeCb).not.toHaveBeenCalled();
3318+
expect(mockSelection.add_items).toHaveBeenCalledWith(combo.id, ['test'], true);
3319+
expect(mockSelection.select_items).toHaveBeenCalledWith(combo.id, ['test'], true);
3320+
expect(combo.value).toBe('test');
3321+
3322+
// setDisabledState
3323+
combo.setDisabledState(true);
3324+
expect(combo.disabled).toBe(true);
3325+
combo.setDisabledState(false);
3326+
expect(combo.disabled).toBe(false);
3327+
3328+
// OnChange callback
3329+
mockSelection.add_items.and.returnValue(new Set(['simpleValue']));
3330+
combo.selectItems(['simpleValue']);
3331+
expect(mockSelection.add_items).toHaveBeenCalledWith(combo.id, ['simpleValue'], undefined);
3332+
expect(mockSelection.select_items).toHaveBeenCalledWith(combo.id, ['simpleValue'], true);
3333+
expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledWith(['simpleValue']);
3334+
3335+
// OnTouched callback
3336+
spyOnProperty(combo, 'collapsed').and.returnValue(true);
3337+
3338+
combo.onFocus();
3339+
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(1);
3340+
3341+
combo.onBlur();
3342+
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(2);
3343+
});
3344+
3345+
it('should correctly handle ngControl validity', () => {
3346+
pending('Convert existing form test here');
3347+
});
3348+
});
32713349
@Component({
32723350
template: `
32733351
<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
@@ -155,6 +155,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
155155
private _itemHeight = null;
156156
private _itemsMaxHeight = null;
157157
private _onChangeCallback: (_: any) => void = noop;
158+
private _onTouchedCallback: () => void = noop;
158159
private _overlaySettings: OverlaySettings = {
159160
scrollStrategy: new AbsoluteScrollStrategy(),
160161
positionStrategy: new ConnectedPositioningStrategy(),
@@ -1254,6 +1255,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
12541255
*/
12551256
public onBlur() {
12561257
if (this.collapsed) {
1258+
this._onTouchedCallback();
12571259
if (this.ngControl && !this.ngControl.valid) {
12581260
this.valid = IgxComboState.INVALID;
12591261
} else {
@@ -1262,6 +1264,13 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
12621264
}
12631265
}
12641266

1267+
/** @hidden @internal */
1268+
public onFocus() {
1269+
if (this.collapsed) {
1270+
this._onTouchedCallback();
1271+
}
1272+
}
1273+
12651274
/**
12661275
* @hidden @internal
12671276
*/
@@ -1326,7 +1335,9 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
13261335
/**
13271336
* @hidden @internal
13281337
*/
1329-
public registerOnTouched(fn: any): void { }
1338+
public registerOnTouched(fn: any): void {
1339+
this._onTouchedCallback = fn;
1340+
}
13301341

13311342
/**
13321343
* @hidden @internal
@@ -1370,6 +1381,11 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
13701381
*/
13711382
public handleClearItems(event: Event): void {
13721383
this.deselectAllItems(true, event);
1384+
if (this.collapsed) {
1385+
this.getEditElement().focus();
1386+
} else {
1387+
this.focusSearchInput(true);
1388+
}
13731389
event.stopPropagation();
13741390
}
13751391

0 commit comments

Comments
 (0)