Skip to content

Commit b9094eb

Browse files
authored
Merge branch '9.1.x' into simeonoff/fix-typography-9.1.x
2 parents 2b84b59 + 5792cff commit b9094eb

File tree

15 files changed

+216
-53
lines changed

15 files changed

+216
-53
lines changed

projects/igniteui-angular/src/lib/calendar/calendar-base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ export class IgxCalendarBaseDirective implements ControlValueAccessor {
379379
const result = [];
380380
start = this.getDateOnly(start);
381381
end = this.getDateOnly(end);
382-
while (start.getTime() !== end.getTime()) {
382+
while (start.getTime() < end.getTime()) {
383383
start = this.calendarModel.timedelta(start, 'day', 1);
384384
result.push(start);
385385
}

projects/igniteui-angular/src/lib/core/styles/base/utilities/_functions.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,12 @@
276276
/// @param {Color} $color - The base color used to generate the palette.
277277
/// @param {Map} $shades - A map of variations as keys and opacities as values.
278278
/// Based on the Material color system.
279-
/// @returns {Map} - A map consisting of 10 grayscale color variations and 10
279+
/// @returns {Map} - A map consisting of 10 color variations and 10
280280
/// text contrast colors for each variation.
281281
@function grayscale-palette($color, $shades) {
282282
$result: ();
283283
@each $saturation, $opacity in $shades {
284-
$shade: rgba(grayscale($color), $opacity);
284+
$shade: rgba($color, $opacity);
285285
$result: map-merge($result, ($saturation: $shade));
286286
}
287287
@return $result;
@@ -297,7 +297,7 @@
297297
/// @param {Color} $success [#4eb862] - The success color used throughout the application.
298298
/// @param {Color} $warn [#fbb13c] - The warning color used throughout the application.
299299
/// @param {Color} $error [#ff134a] - The error color used throughout the application.
300-
/// @param {Color} $grays [#000 | $igx-foreground-color] - The color used for generating the grayscale palette.
300+
/// @param {Color} $grays [#000 | $igx-foreground-color] - The color used for generating the grays palette.
301301
/// @param {Color} $surface [#fff] - The color used as a background in components, such as cards, sheets, and menus.
302302
/// @returns {Map} - A map consisting of 74 color variations, including the `primary`, `secondary`, `grays`,
303303
/// `info`, `success`, `warn`, and `error` colors.

projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.spec.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { IgxDateRangePickerComponent } from './date-range-picker.component';
21
import { ComponentFixture, async, TestBed, fakeAsync, tick } from '@angular/core/testing';
32
import { Component, OnInit, ViewChild, DebugElement } from '@angular/core';
43
import { IgxInputGroupModule } from '../input-group/public_api';
@@ -13,6 +12,8 @@ import { configureTestSuite } from '../test-utils/configure-suite';
1312
import { HelperTestFunctions } from '../calendar/calendar-helper-utils';
1413
import { IgxDateTimeEditorModule } from '../directives/date-time-editor/public_api';
1514
import { DateRangeType } from '../core/dates';
15+
import { IgxDateRangePickerComponent, IgxDateRangeEndComponent } from './public_api';
16+
import { IgxIconModule } from '../icon/public_api';
1617

1718
// The number of milliseconds in one day
1819
const ONE_DAY = 1000 * 60 * 60 * 24;
@@ -494,7 +495,8 @@ describe('IgxDateRangePicker', () => {
494495
DateRangeTwoInputsTestComponent,
495496
DateRangeTwoInputsNgModelTestComponent
496497
],
497-
imports: [IgxDateRangePickerModule, IgxDateTimeEditorModule, IgxInputGroupModule, FormsModule, NoopAnimationsModule]
498+
imports: [IgxDateRangePickerModule, IgxDateTimeEditorModule,
499+
IgxInputGroupModule, FormsModule, NoopAnimationsModule, IgxIconModule]
498500
})
499501
.compileComponents();
500502
}));
@@ -633,6 +635,43 @@ describe('IgxDateRangePicker', () => {
633635
}));
634636
});
635637

638+
it('should focus the last focused input after the calendar closes - dropdown', fakeAsync(() => {
639+
fixture.componentInstance.mode = InteractionMode.DropDown;
640+
fixture.detectChanges();
641+
642+
endInput = fixture.debugElement.queryAll(By.css('.igx-input-group'))[1];
643+
UIInteractions.simulateClickAndSelectEvent(endInput.nativeElement);
644+
645+
UIInteractions.triggerEventHandlerKeyDown('ArrowDown', endInput, true);
646+
tick();
647+
fixture.detectChanges();
648+
649+
UIInteractions.triggerEventHandlerKeyDown('Escape', calendar);
650+
fixture.detectChanges();
651+
tick(100);
652+
653+
expect(fixture.componentInstance.dateRange.projectedInputs
654+
.find(i => i instanceof IgxDateRangeEndComponent).isFocused)
655+
.toBeTruthy();
656+
}));
657+
658+
it('should focus the last focused input after the calendar closes - dialog', fakeAsync(() => {
659+
endInput = fixture.debugElement.queryAll(By.css('.igx-input-group'))[1];
660+
UIInteractions.simulateClickAndSelectEvent(endInput.nativeElement);
661+
662+
UIInteractions.triggerEventHandlerKeyDown('ArrowDown', endInput, true);
663+
tick();
664+
fixture.detectChanges();
665+
666+
UIInteractions.triggerEventHandlerKeyDown('Escape', calendar);
667+
fixture.detectChanges();
668+
tick(100);
669+
670+
expect(fixture.componentInstance.dateRange.projectedInputs
671+
.find(i => i instanceof IgxDateRangeEndComponent).isFocused)
672+
.toBeTruthy();
673+
}));
674+
636675
describe('Data binding', () => {
637676
it('should properly update component value with ngModel bound to projected inputs - #7353', fakeAsync(() => {
638677
fixture = TestBed.createComponent(DateRangeTwoInputsNgModelTestComponent);
@@ -822,6 +861,9 @@ export class DateRangeTestComponent implements OnInit {
822861
template: `
823862
<igx-date-range-picker [mode]="mode" [(ngModel)]="range" required>
824863
<igx-date-range-start>
864+
<igx-picker-toggle igxPrefix>
865+
<igx-icon>calendar_view_day</igx-icon>
866+
</igx-picker-toggle>
825867
<input igxInput igxDateTimeEditor type="text">
826868
</igx-date-range-start>
827869
<igx-date-range-end>

projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,13 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
415415
private _value: DateRange;
416416
private _collapsed = true;
417417
private _ngControl: NgControl;
418-
private _statusChanges$: Subscription;
419418
private $destroy = new Subject();
419+
private _statusChanges$: Subscription;
420+
private $toggleClickNotifier = new Subject();
420421
private _minValue: Date | string;
421422
private _maxValue: Date | string;
422-
private $toggleClickNotifier = new Subject();
423423
private _positionSettings: PositionSettings;
424+
private _focusedInput: IgxDateRangeInputsBaseComponent;
424425
private _dialogOverlaySettings: OverlaySettings = {
425426
closeOnOutsideClick: true,
426427
modal: true
@@ -620,6 +621,7 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
620621
this.subscribeToDateEditorEvents();
621622
this.configPositionStrategy();
622623
this.configOverlaySettings();
624+
this.cacheFocusedInput();
623625
this.attachOnTouched();
624626

625627
const subsToClicked = () => {
@@ -688,7 +690,13 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
688690
this.updateValidityOnBlur();
689691
} else {
690692
// input click
691-
this.focusInput();
693+
if (this.hasProjectedInputs && this._focusedInput) {
694+
this._focusedInput.setFocus();
695+
this._focusedInput = null;
696+
}
697+
if (this.inputDirective) {
698+
this.inputDirective.focus();
699+
}
692700
}
693701
}
694702

@@ -715,15 +723,6 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
715723
}
716724
}
717725

718-
private focusInput() {
719-
// TODO: should we always focus start input?
720-
(this.projectedInputs
721-
.find(i => i instanceof IgxDateRangeStartComponent) as IgxDateRangeStartComponent)?.setFocus();
722-
if (this.inputDirective) {
723-
this.inputDirective.focus();
724-
}
725-
}
726-
727726
/** @hidden @internal */
728727
public handleClosed(): void {
729728
this._collapsed = true;
@@ -901,6 +900,16 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
901900
}
902901
}
903902

903+
private cacheFocusedInput(): void {
904+
if (this.hasProjectedInputs) {
905+
this.projectedInputs.forEach(i => {
906+
fromEvent(i.dateTimeEditor.nativeElement, 'focus')
907+
.pipe(takeUntil(this.$destroy))
908+
.subscribe(() => this._focusedInput = i);
909+
});
910+
}
911+
}
912+
904913
private configPositionStrategy(): void {
905914
this._positionSettings = {
906915
openAnimation: fadeIn,

projects/igniteui-angular/src/lib/directives/autocomplete/autocomplete.directive.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,31 @@ describe('IgxAutocomplete', () => {
592592
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
593593
expect(fixture.componentInstance.townSelected).toBe('s');
594594
}));
595+
it('Should trigger onItemSelected only once when the event is cancelled (issue #7483)', fakeAsync(() => {
596+
spyOn(autocomplete.onItemSelected, 'emit').and.callThrough();
597+
598+
fixture.componentInstance.onItemSelected = (args) => { args.cancel = true; };
599+
UIInteractions.setInputElementValue(input, 's', fixture);
600+
fixture.detectChanges();
601+
tick();
602+
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
603+
expect(fixture.componentInstance.townSelected).toBe('s');
604+
tick();
605+
fixture.detectChanges();
606+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledTimes(1);
607+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledWith({ value: 'Sofia', cancel: true });
608+
609+
fixture.componentInstance.onItemSelected = (args) => { args.cancel = true; };
610+
UIInteractions.setInputElementValue(input, 's', fixture);
611+
fixture.detectChanges();
612+
tick();
613+
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
614+
expect(fixture.componentInstance.townSelected).toBe('s');
615+
tick();
616+
fixture.detectChanges();
617+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledTimes(2);
618+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledWith({ value: 'Sofia', cancel: true });
619+
}));
595620
it('Should call onInput/open/close methods properly', fakeAsync(() => {
596621
let startsWith = 'g';
597622
spyOn(autocomplete, 'onInput').and.callThrough();

projects/igniteui-angular/src/lib/directives/autocomplete/autocomplete.directive.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
} from '@angular/core';
1616
import { NgModel, FormControlName } from '@angular/forms';
1717
import { CommonModule } from '@angular/common';
18-
import { Subject } from 'rxjs';
18+
import { Subject, Subscription } from 'rxjs';
1919
import { first, takeUntil } from 'rxjs/operators';
2020
import { CancelableEventArgs, IBaseEventArgs } from '../../core/utils';
2121
import {
@@ -91,6 +91,9 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective
9191
excludePositionTarget: true
9292
};
9393

94+
/** @hidden @internal */
95+
private subscriptions: Subscription[] = [];
96+
9497
protected id: string;
9598
protected dropDownOpened$ = new Subject<boolean>();
9699
protected get model() {
@@ -303,9 +306,18 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective
303306
// if no drop-down width is set, the drop-down will be as wide as the autocomplete input;
304307
this.target.width = this.target.width || (this.parentElement.clientWidth + 'px');
305308
this.target.open(this.settings);
306-
this.target.onSelection.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.select);
307-
this.target.onOpened.pipe(first()).subscribe(this.highlightFirstItem);
308-
this.target.children.changes.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.highlightFirstItem);
309+
310+
// unsubscribe from previous subscriptions, before creating new subscriptions.
311+
this.unsubscribe();
312+
313+
this.subscriptions.push(this.target.onSelection.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.select));
314+
this.subscriptions.push(this.target.onOpened.pipe(first()).subscribe(this.highlightFirstItem));
315+
this.subscriptions.push(this.target.children.changes.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.highlightFirstItem));
316+
}
317+
318+
/** @hidden @internal */
319+
private unsubscribe() {
320+
this.subscriptions.forEach(subscription => subscription.unsubscribe());
309321
}
310322

311323
private get collapsed(): boolean {

projects/igniteui-angular/src/lib/directives/text-highlight/text-highlight.directive.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
} from '@angular/core';
1414
import { takeUntil } from 'rxjs/operators';
1515
import { Subject } from 'rxjs';
16-
import { DeprecateProperty } from '../../core/deprecateDecorators';
1716
import { compareMaps } from '../../core/utils';
1817

1918
interface ISearchInfo {

projects/igniteui-angular/src/lib/grids/api.service.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -546,10 +546,6 @@ export class GridBaseAPIService <T extends IgxGridBaseDirective & GridType> {
546546
return false;
547547
}
548548

549-
public atInexistingPage(): boolean {
550-
return this.grid.totalPages - 1 > this.grid.page;
551-
}
552-
553549
public get_row_expansion_state(record: any): boolean {
554550
const grid = this.grid;
555551
const states = grid.expansionStates;

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ export class IgxFilteringService implements OnDestroy {
211211
}
212212

213213
/**
214-
* Clear the filter of a given column.
214+
* Clears the filter of a given column if name is provided. Otherwise clears the filters of all columns.
215215
*/
216216
public clearFilter(field: string): void {
217217
if (field) {
@@ -231,6 +231,11 @@ export class IgxFilteringService implements OnDestroy {
231231
if (field) {
232232
const expressions = this.getExpressions(field);
233233
expressions.length = 0;
234+
} else {
235+
this.grid.columns.forEach(c => {
236+
const expressions = this.getExpressions(c.field);
237+
expressions.length = 0;
238+
});
234239
}
235240

236241
this.isFiltering = false;

projects/igniteui-angular/src/lib/grids/grid-base.directive.ts

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import { FilteringLogic, IFilteringExpression } from '../data-operations/filteri
3737
import { IGroupByRecord } from '../data-operations/groupby-record.interface';
3838
import { ISortingExpression } from '../data-operations/sorting-expression.interface';
3939
import { IForOfState, IgxGridForOfDirective } from '../directives/for-of/for_of.directive';
40-
import { IgxTextHighlightDirective, IActiveHighlightInfo } from '../directives/text-highlight/text-highlight.directive';
40+
import { IgxTextHighlightDirective } from '../directives/text-highlight/text-highlight.directive';
4141
import {
4242
AbsoluteScrollStrategy,
4343
HorizontalAlignment,
@@ -2861,12 +2861,6 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
28612861
this.summaryService.clearSummaryCache();
28622862
this._pipeTrigger++;
28632863
this.notifyChanges();
2864-
if (this.transactions.getAggregatedChanges(false).length === 0) {
2865-
// Needs better check, calling 'transactions.clear()' will also trigger this
2866-
if (this.gridAPI.atInexistingPage()) {
2867-
this.page--;
2868-
}
2869-
}
28702864
});
28712865

28722866
this.resizeNotify.pipe(destructor, filter(() => !this._init), throttleTime(100, undefined, {leading: true, trailing: true}))
@@ -2999,7 +2993,11 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
29992993
}
30002994
}
30012995

3002-
public setFilterData(data, pinned: boolean) {
2996+
/**
2997+
* @hidden
2998+
* @internal
2999+
*/
3000+
public setFilteredData(data, pinned: boolean) {
30033001
if (this.hasPinnedRecords && pinned) {
30043002
this._filteredPinnedData = data || [];
30053003
const filteredUnpinned = this._filteredUnpinnedData || [];
@@ -3064,12 +3062,14 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
30643062
if (this.pinnedRecordsCount > 0 && pinned) {
30653063
this._filteredSortedPinnedData = data;
30663064
this.pinnedRecords = data;
3067-
this.filteredSortedData = this.isRowPinningToTop ? [... this._filteredSortedPinnedData, ... this._filteredSortedUnpinnedData] :
3065+
this._filteredSortedData = this.isRowPinningToTop ? [... this._filteredSortedPinnedData, ... this._filteredSortedUnpinnedData] :
30683066
[... this._filteredSortedUnpinnedData, ... this._filteredSortedPinnedData];
3067+
this.refreshSearch(true, false);
30693068
} else if (this.pinnedRecordsCount > 0 && !pinned) {
30703069
this._filteredSortedUnpinnedData = data;
30713070
} else {
3072-
this.filteredSortedData = data;
3071+
this._filteredSortedData = data;
3072+
this.refreshSearch(true, false);
30733073
}
30743074
}
30753075

@@ -4386,7 +4386,7 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
43864386
* ```
43874387
* @param updateActiveInfo
43884388
*/
4389-
public refreshSearch(updateActiveInfo?: boolean): number {
4389+
public refreshSearch(updateActiveInfo?: boolean, endEdit = true): number {
43904390
if (this.lastSearchInfo.searchText) {
43914391
this.rebuildMatchCache();
43924392

@@ -4402,7 +4402,12 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
44024402
});
44034403
}
44044404

4405-
return this.find(this.lastSearchInfo.searchText, 0, this.lastSearchInfo.caseSensitive, this.lastSearchInfo.exactMatch, false);
4405+
return this.find(this.lastSearchInfo.searchText,
4406+
0,
4407+
this.lastSearchInfo.caseSensitive,
4408+
this.lastSearchInfo.exactMatch,
4409+
false,
4410+
endEdit);
44064411
} else {
44074412
return 0;
44084413
}
@@ -5907,12 +5912,14 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
59075912
return col.field + col._calcWidth;
59085913
}
59095914

5910-
private find(text: string, increment: number, caseSensitive?: boolean, exactMatch?: boolean, scroll?: boolean) {
5915+
private find(text: string, increment: number, caseSensitive?: boolean, exactMatch?: boolean, scroll?: boolean, endEdit = true) {
59115916
if (!this.rowList) {
59125917
return 0;
59135918
}
59145919

5915-
this.endEdit(false);
5920+
if (endEdit) {
5921+
this.endEdit(false);
5922+
}
59165923

59175924
if (!text) {
59185925
this.clearSearch();
@@ -5989,10 +5996,6 @@ export class IgxGridBaseDirective extends DisplayDensityBase implements
59895996
get filteredSortedData(): any[] {
59905997
return this._filteredSortedData;
59915998
}
5992-
set filteredSortedData(value: any[]) {
5993-
this._filteredSortedData = value;
5994-
this.refreshSearch(true);
5995-
}
59965999

59976000
/**
59986001
* @hidden

0 commit comments

Comments
 (0)