Skip to content

Commit 41ec1d6

Browse files
committed
Merge branch '8.2.x' into dmdimitrov/issue5993-8.2.x
2 parents adf8b79 + 158af8f commit 41ec1d6

File tree

5 files changed

+104
-5
lines changed

5 files changed

+104
-5
lines changed

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: 80 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, IComboSelectionChangeEventArgs, IgxComboState } 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';
@@ -3302,6 +3302,25 @@ describe('igxCombo', () => {
33023302
fixture.detectChanges();
33033303
expect(component.selectedItems).toEqual([combo.data[0], combo.data[2], combo.data[4]]);
33043304
}));
3305+
3306+
it('Should have correctly bound focus and blur handlers', () => {
3307+
const fixture = TestBed.createComponent(IgxComboInTemplatedFormComponent);
3308+
fixture.detectChanges();
3309+
const combo = fixture.componentInstance.testCombo;
3310+
const input = fixture.debugElement.query(By.css(`${CSS_CLASS_INPUTGROUP} input`));
3311+
3312+
spyOn(combo, 'onFocus');
3313+
spyOn(combo, 'onBlur');
3314+
3315+
3316+
input.triggerEventHandler('focus', {});
3317+
expect(combo.onFocus).toHaveBeenCalled();
3318+
expect(combo.onFocus).toHaveBeenCalledWith();
3319+
3320+
input.triggerEventHandler('blur', {});
3321+
expect(combo.onBlur).toHaveBeenCalled();
3322+
expect(combo.onFocus).toHaveBeenCalledWith();
3323+
});
33053324
});
33063325

33073326
describe('Combo - Display Density', () => {
@@ -3374,6 +3393,66 @@ describe('igxCombo', () => {
33743393
});
33753394
});
33763395

3396+
describe('Combo ControlValueAccessor Unit', () => {
3397+
let combo: IgxComboComponent;
3398+
it('should correctly implement interface methods', () => {
3399+
const mockSelection: {
3400+
[key: string]: jasmine.Spy
3401+
} = jasmine.createSpyObj('IgxSelectionAPIService', ['get', 'set', 'add_items', 'select_items']);
3402+
const mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['markForCheck']);
3403+
const mockComboService = jasmine.createSpyObj('IgxComboAPIService', ['register']);
3404+
const mockNgControl = jasmine.createSpyObj('NgControl', ['registerOnChangeCb', 'registerOnTouchedCb']);
3405+
const mockInjector = jasmine.createSpyObj('Injector', {
3406+
'get': mockNgControl
3407+
});
3408+
mockSelection.get.and.returnValue(new Set([]));
3409+
3410+
// init
3411+
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
3412+
combo.ngOnInit();
3413+
expect(mockInjector.get).toHaveBeenCalledWith(NgControl, null);
3414+
combo.registerOnChange(mockNgControl.registerOnChangeCb);
3415+
combo.registerOnTouched(mockNgControl.registerOnTouchedCb);
3416+
3417+
// writeValue
3418+
expect(combo.value).toBe('');
3419+
mockSelection.add_items.and.returnValue(new Set(['test']));
3420+
spyOnProperty(combo, 'isRemote').and.returnValue(false);
3421+
combo.writeValue(['test']);
3422+
// TODO: Uncomment after fix for write value going through entire selection process
3423+
// expect(mockNgControl.registerOnChangeCb).not.toHaveBeenCalled();
3424+
expect(mockSelection.add_items).toHaveBeenCalledWith(combo.id, ['test'], true);
3425+
expect(mockSelection.select_items).toHaveBeenCalledWith(combo.id, ['test'], true);
3426+
expect(combo.value).toBe('test');
3427+
3428+
// setDisabledState
3429+
combo.setDisabledState(true);
3430+
expect(combo.disabled).toBe(true);
3431+
combo.setDisabledState(false);
3432+
expect(combo.disabled).toBe(false);
3433+
3434+
// OnChange callback
3435+
mockSelection.add_items.and.returnValue(new Set(['simpleValue']));
3436+
combo.selectItems(['simpleValue']);
3437+
expect(mockSelection.add_items).toHaveBeenCalledWith(combo.id, ['simpleValue'], undefined);
3438+
expect(mockSelection.select_items).toHaveBeenCalledWith(combo.id, ['simpleValue'], true);
3439+
expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledWith(['simpleValue']);
3440+
3441+
// OnTouched callback
3442+
spyOnProperty(combo, 'collapsed').and.returnValue(true);
3443+
spyOnProperty(combo, 'valid', 'set');
3444+
3445+
combo.onFocus();
3446+
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(1);
3447+
3448+
combo.onBlur();
3449+
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(2);
3450+
});
3451+
3452+
it('should correctly handle ngControl validity', () => {
3453+
pending('Convert existing form test here');
3454+
});
3455+
});
33773456
@Component({
33783457
template: `
33793458
<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
@@ -157,6 +157,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
157157
private _itemsMaxHeight = null;
158158
private _remoteSelection = {};
159159
private _onChangeCallback: (_: any) => void = noop;
160+
private _onTouchedCallback: () => void = noop;
160161
private _overlaySettings: OverlaySettings = {
161162
scrollStrategy: new AbsoluteScrollStrategy(),
162163
positionStrategy: new ConnectedPositioningStrategy(),
@@ -1260,6 +1261,7 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
12601261
*/
12611262
public onBlur() {
12621263
if (this.collapsed) {
1264+
this._onTouchedCallback();
12631265
if (this.ngControl && !this.ngControl.valid) {
12641266
this.valid = IgxComboState.INVALID;
12651267
} else {
@@ -1268,6 +1270,13 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
12681270
}
12691271
}
12701272

1273+
/** @hidden @internal */
1274+
public onFocus() {
1275+
if (this.collapsed) {
1276+
this._onTouchedCallback();
1277+
}
1278+
}
1279+
12711280
/**
12721281
* @hidden @internal
12731282
*/
@@ -1333,7 +1342,9 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
13331342
/**
13341343
* @hidden @internal
13351344
*/
1336-
public registerOnTouched(fn: any): void { }
1345+
public registerOnTouched(fn: any): void {
1346+
this._onTouchedCallback = fn;
1347+
}
13371348

13381349
/**
13391350
* @hidden @internal
@@ -1377,6 +1388,11 @@ export class IgxComboComponent extends DisplayDensityBase implements IgxComboBas
13771388
*/
13781389
public handleClearItems(event: Event): void {
13791390
this.deselectAllItems(true, event);
1391+
if (this.collapsed) {
1392+
this.getEditElement().focus();
1393+
} else {
1394+
this.focusSearchInput(true);
1395+
}
13801396
event.stopPropagation();
13811397
}
13821398

projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid-navigation.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,8 @@ export class IgxHierarchicalGridNavigationService extends IgxGridNavigationServi
675675
}
676676

677677
private focusNextRow(elem, visibleColumnIndex, grid, isSummary?) {
678+
const lastCellIndex = grid.unpinnedColumns[grid.unpinnedColumns.length - 1].visibleIndex;
679+
visibleColumnIndex = Math.min(lastCellIndex, visibleColumnIndex);
678680
const cellSelector = this.getCellSelector(visibleColumnIndex, isSummary);
679681
if (grid.navigation.isColumnFullyVisible(visibleColumnIndex) || grid.rowList.length === 0) {
680682
const cell =
@@ -707,6 +709,8 @@ export class IgxHierarchicalGridNavigationService extends IgxGridNavigationServi
707709
}
708710

709711
private focusPrevRow(elem, visibleColumnIndex, grid, inChild?, isSummary?) {
712+
const lastCellIndex = grid.unpinnedColumns[grid.unpinnedColumns.length - 1].visibleIndex;
713+
visibleColumnIndex = Math.min(lastCellIndex, visibleColumnIndex);
710714
if (grid.navigation.isColumnFullyVisible(visibleColumnIndex)) {
711715
const cellSelector = this.getCellSelector(visibleColumnIndex, isSummary);
712716
const cells = elem.querySelectorAll(`${cellSelector}[data-visibleIndex="${visibleColumnIndex}"]`);

src/app/combo/combo.sample.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
<h5 class="sample-title">Template Form</h5>
7171
<form>
7272
<igx-combo class="input-container" [placeholder]="'Locations'"
73-
name="anyName" required [(ngModel)]="values1"
73+
name="anyName" required [(ngModel)]="values1" [ngModelOptions]="{ updateOn: 'blur' }" #comboModel="ngModel"
7474
[data]="items" [filterable]="filterableFlag"
7575
[displayKey]="valueKeyVar" [valueKey]="valueKeyVar"
7676
[groupKey]="valueKeyVar ? 'region' : ''" [width]="'100%'">

0 commit comments

Comments
 (0)