Skip to content

Commit 9fb6948

Browse files
authored
Merge branch 'master' into mkirova/resizing-percentage-width
2 parents 994d21c + 5e91c8e commit 9fb6948

File tree

52 files changed

+1215
-465
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1215
-465
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@ All notable changes for each version of this project will be documented in this
1212
- `IgxTransaction` - The `onStateUpdate` now emits with information of its origin. The emitted value is of type `StateUpdateEvent`, which has two properties:
1313
- `origin` - it can vary within the values of the `TransactionEventOrigin` interface;
1414
- `actions` - contains information about the transactions, that caused the emission of the event.
15+
- `IgxPaginator` - The input `overlaySettings` was introduced, which allows applying custom overlay settings for the component.
1516

1617
### New Features
1718
- `IgxGrid`
1819
- `showGroupArea` input is added, which can be used to enable/disable the group area row.
20+
- The event arguments of `onCellEdit`, `onCellEditEnter` and `onCellEditCancel` events will contain a reference to the row data, as well as a reference to the column.
21+
- The event arguments of `onRowEdit`, `onRowEditEnter` and `onRowEditCancel` events will contain a reference to the row data.
22+
23+
- `IgxSelect` support for `igxHint` directive added.
24+
- Allows the user to add `igxHint` to be displayed bellow the input element.
1925

2026
## 9.1.1
2127

projects/igniteui-angular/src/lib/core/styles/components/grid/_excel-filtering-theme.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@
387387
align-items: center;
388388
padding: 0 rem(16px);
389389

390-
igx-input-group {
390+
igx-select {
391391
flex-grow: 1;
392392
flex-basis: 40%;
393393
margin: rem(16px) 0;

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,22 @@ describe('IgxDatePicker', () => {
132132
expect(inputGroup.nativeElement.classList.contains('igx-input-group--disabled')).toBeTruthy();
133133
});
134134

135+
it('should not be able to toggle & clear when disabled', () => {
136+
const date = new Date();
137+
datePicker.value = date;
138+
datePicker.disabled = true;
139+
fixture.detectChanges();
140+
expect(datePicker.collapsed).toBeTruthy();
141+
142+
datePicker.openDialog();
143+
fixture.detectChanges();
144+
expect(datePicker.collapsed).toBeTruthy();
145+
146+
datePicker.clear();
147+
fixture.detectChanges();
148+
expect(datePicker.value).toEqual(date);
149+
});
150+
135151
it('When labelVisability is set to false the label should not be visible', () => {
136152
let label = fixture.debugElement.query(By.directive(IgxLabelDirective));
137153

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

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import { IgxInputGroupModule, IgxInputDirective, IgxInputGroupComponent, IgxInpu
3434
import { Subject, fromEvent, animationFrameScheduler, interval, Subscription } from 'rxjs';
3535
import { filter, takeUntil, throttle } from 'rxjs/operators';
3636
import { IgxOverlayOutletDirective } from '../directives/toggle/toggle.directive';
37-
import { IgxTextSelectionModule} from '../directives/text-selection/text-selection.directive';
37+
import { IgxTextSelectionModule } from '../directives/text-selection/text-selection.directive';
3838
import {
3939
OverlaySettings,
4040
IgxOverlayService,
@@ -144,7 +144,7 @@ const noop = () => { };
144144
`]
145145
})
146146
export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor,
147-
EditorProvider, OnInit, AfterViewInit, OnDestroy, AfterViewChecked {
147+
EditorProvider, OnInit, AfterViewInit, OnDestroy, AfterViewChecked {
148148
/**
149149
* Gets/Sets the `IgxDatePickerComponent` label.
150150
* @remarks
@@ -914,10 +914,10 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
914914
* @param date passed date that has to be set to the calendar.
915915
*/
916916
public selectDate(date: Date): void {
917-
const oldValue = this.value;
917+
const oldValue = this.value;
918918
this.value = date;
919919

920-
this.emitValueChangeEvent(oldValue, this.value );
920+
this.emitValueChangeEvent(oldValue, this.value);
921921
this.onSelection.emit(date);
922922
}
923923

@@ -929,9 +929,9 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
929929
* ```
930930
*/
931931
public deselectDate(): void {
932-
const oldValue = this.value;
932+
const oldValue = this.value;
933933
this.value = null;
934-
this.emitValueChangeEvent(oldValue, this.value );
934+
this.emitValueChangeEvent(oldValue, this.value);
935935
if (this.calendar) {
936936
this.calendar.deselectDate();
937937
}
@@ -946,7 +946,7 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
946946
* ```
947947
*/
948948
public openDialog(): void {
949-
if (!this.collapsed) {
949+
if (!this.collapsed || this.disabled) {
950950
return;
951951
}
952952

@@ -987,10 +987,12 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
987987
* @hidden @internal
988988
*/
989989
public clear(): void {
990-
this.isEmpty = true;
991-
this.invalidDate = '';
992-
this.deselectDate();
993-
this._setCursorPosition(0);
990+
if (!this.disabled) {
991+
this.isEmpty = true;
992+
this.invalidDate = '';
993+
this.deselectDate();
994+
this._setCursorPosition(0);
995+
}
994996
}
995997

996998
/**
@@ -1008,10 +1010,10 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
10081010
date.setSeconds(this.value.getSeconds());
10091011
date.setMilliseconds(this.value.getMilliseconds());
10101012
}
1011-
const oldValue = this.value;
1013+
const oldValue = this.value;
10121014
this.value = date;
10131015

1014-
this.emitValueChangeEvent(oldValue, this.value );
1016+
this.emitValueChangeEvent(oldValue, this.value);
10151017
this.calendar.viewDate = date;
10161018
this.closeCalendar();
10171019
this.onSelection.emit(date);
@@ -1141,11 +1143,11 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
11411143

11421144
if (this.disabledDates === null
11431145
|| (this.disabledDates !== null && !isDateInRanges(newValue, this.disabledDates))) {
1144-
const oldValue = this.value;
1145-
this.value = newValue;
1146+
const oldValue = this.value;
1147+
this.value = newValue;
11461148

1147-
this.emitValueChangeEvent(oldValue, this.value );
1148-
this.invalidDate = '';
1149+
this.emitValueChangeEvent(oldValue, this.value);
1150+
this.invalidDate = '';
11491151
} else {
11501152
const args: IDatePickerDisabledDateEventArgs = {
11511153
datePicker: this,

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,34 @@ describe('IgxDateRangePicker', () => {
586586
fixture.detectChanges();
587587
verifyDateRange();
588588
});
589+
590+
it('should select a range from the calendar only when the two inputs are filled in', fakeAsync(() => {
591+
fixture.componentInstance.mode = InteractionMode.DropDown;
592+
fixture.detectChanges();
593+
594+
startInput.triggerEventHandler('focus', {});
595+
fixture.detectChanges();
596+
UIInteractions.simulateTyping('11/10/2015', startInput);
597+
598+
fixture.componentInstance.dateRange.open();
599+
tick();
600+
fixture.detectChanges();
601+
expect(fixture.componentInstance.dateRange.calendar.selectedDates.length).toBe(0);
602+
603+
UIInteractions.triggerEventHandlerKeyDown('Escape', calendar);
604+
tick();
605+
fixture.detectChanges();
606+
607+
endInput.triggerEventHandler('focus', {});
608+
fixture.detectChanges();
609+
UIInteractions.simulateTyping('11/16/2015', endInput);
610+
fixture.detectChanges();
611+
612+
fixture.componentInstance.dateRange.open();
613+
tick();
614+
fixture.detectChanges();
615+
expect(fixture.componentInstance.dateRange.calendar.selectedDates.length).toBe(7);
616+
}));
589617
});
590618

591619
describe('Keyboard navigation', () => {

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

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -570,11 +570,23 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
570570
public validate(control: AbstractControl): ValidationErrors | null {
571571
const value: DateRange = control.value;
572572
if (value) {
573+
// TODO (in issue #7477)
574+
// Accumulate all errors and return them as one object.
575+
if (this.hasProjectedInputs) {
576+
const startInput = this.projectedInputs.find(i => i instanceof IgxDateRangeStartComponent) as IgxDateRangeStartComponent;
577+
const endInput = this.projectedInputs.find(i => i instanceof IgxDateRangeEndComponent) as IgxDateRangeEndComponent;
578+
if (!startInput.dateTimeEditor.value) {
579+
return { 'startValue': true };
580+
}
581+
if (!endInput.dateTimeEditor.value) {
582+
return { 'endValue': true };
583+
}
584+
}
585+
573586
const min = DatePickerUtil.parseDate(this.minValue);
574587
const max = DatePickerUtil.parseDate(this.maxValue);
575588
const start = DatePickerUtil.parseDate(value.start);
576589
const end = DatePickerUtil.parseDate(value.end);
577-
578590
if (min && start && DatePickerUtil.lessThanMinValue(start, min, false)) {
579591
return { 'minValue': true };
580592
}
@@ -589,7 +601,6 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
589601
}
590602
}
591603

592-
// TODO: fix what happens on blur and ensure on blur the value is either null or with both start and end filled
593604
return null;
594605
}
595606

@@ -676,15 +687,12 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
676687

677688
/** @hidden @internal */
678689
public handleClosing(event: CancelableBrowserEventArgs & IBaseEventArgs): void {
679-
this.onClosing.emit(event);
680-
681-
if (this.value && this.value.start && !this.value.end) {
682-
this.value = { start: this.value.start, end: this.value.start };
683-
}
684690
if (this.value && !this.value.start && !this.value.end) {
685691
this.value = null;
686692
}
687693

694+
this.onClosing.emit(event);
695+
688696
if (this.mode === InteractionMode.DropDown && event.event && !this.element.nativeElement.contains(event.event.target)) {
689697
// outside click
690698
this.updateValidityOnBlur();
@@ -790,46 +798,77 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
790798
});
791799
}
792800

793-
private updateCalendar(): void {
794-
this.calendar.disabledDates = [];
795-
let minValue: Date = DatePickerUtil.parseDate(this.minValue);
801+
private parseMinValue(value: string | Date): Date | null {
802+
let minValue: Date = DatePickerUtil.parseDate(value);
796803
if (!minValue && this.hasProjectedInputs) {
797804
const start = this.projectedInputs.filter(i => i instanceof IgxDateRangeStartComponent)[0];
798805
if (start) {
799806
minValue = DatePickerUtil.parseDate(start.dateTimeEditor.minValue);
800807
}
801808
}
802-
if (minValue) {
803-
this.calendar.disabledDates.push({ type: DateRangeType.Before, dateRange: [minValue] });
804-
}
805809

806-
let maxValue: Date = DatePickerUtil.parseDate(this.maxValue);
807-
if (!maxValue && this.hasProjectedInputs) {
810+
return minValue;
811+
}
812+
813+
private parseMaxValue(value: string | Date): Date | null {
814+
let maxValue: Date = DatePickerUtil.parseDate(value);
815+
if (!maxValue && this.projectedInputs) {
808816
const end = this.projectedInputs.filter(i => i instanceof IgxDateRangeEndComponent)[0];
809817
if (end) {
810818
maxValue = DatePickerUtil.parseDate(end.dateTimeEditor.maxValue);
811819
}
812820
}
821+
822+
return maxValue;
823+
}
824+
825+
private updateCalendar(): void {
826+
this.calendar.disabledDates = [];
827+
const minValue = this.parseMinValue(this.minValue);
828+
if (minValue) {
829+
this.calendar.disabledDates.push({ type: DateRangeType.Before, dateRange: [minValue] });
830+
}
831+
const maxValue = this.parseMaxValue(this.maxValue);
813832
if (maxValue) {
814833
this.calendar.disabledDates.push({ type: DateRangeType.After, dateRange: [maxValue] });
815834
}
816835

817836
const range: Date[] = [];
818-
if (this.value) {
819-
if (this.value.start) {
820-
range.push(this.value.start);
837+
if (this.value?.start && this.value?.end) {
838+
if (DatePickerUtil.greaterThanMaxValue(this.value.start, this.value.end)) {
839+
this.swapEditorDates();
821840
}
822-
if (this.value.end) {
823-
range.push(this.value.end);
841+
if (this.valueInRange(this.value, minValue, maxValue)) {
842+
range.push(this.value.start, this.value.end);
824843
}
825844
}
826845

827846
if (range.length > 0) {
828847
this.calendar.selectDate(range);
829-
this.calendar.viewDate = range[0];
830848
} else {
831849
this.calendar.deselectDate();
832850
}
851+
this.calendar.viewDate = range[0] || new Date();
852+
}
853+
854+
private swapEditorDates(): void {
855+
if (this.hasProjectedInputs) {
856+
const start = this.projectedInputs.find(i => i instanceof IgxDateRangeStartComponent) as IgxDateRangeStartComponent;
857+
const end = this.projectedInputs.find(i => i instanceof IgxDateRangeEndComponent) as IgxDateRangeEndComponent;
858+
[start.dateTimeEditor.value, end.dateTimeEditor.value] = [end.dateTimeEditor.value, start.dateTimeEditor.value];
859+
[this.value.start, this.value.end] = [this.value.end, this.value.start];
860+
}
861+
}
862+
863+
private valueInRange(value: DateRange, minValue?: Date, maxValue?: Date): boolean {
864+
if (minValue && DatePickerUtil.lessThanMinValue(value.start, minValue, false)) {
865+
return false;
866+
}
867+
if (maxValue && DatePickerUtil.greaterThanMaxValue(value.end, maxValue, false)) {
868+
return false;
869+
}
870+
871+
return true;
833872
}
834873

835874
private extractRange(selection: Date[]): DateRange {
@@ -858,7 +897,6 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
858897
} else {
859898
this.value = { start: value, end: null };
860899
}
861-
// TODO: should we check start and reset end value
862900
});
863901
end.dateTimeEditor.valueChange
864902
.pipe(takeUntil(this.$destroy))
@@ -882,11 +920,6 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
882920
if (this.collapsed) {
883921
this.updateValidityOnBlur();
884922
}
885-
if (this.value && !this.value.start) {
886-
this.value = null;
887-
}
888-
// TODO: if we have start and have no end should we fill end
889-
// as we do on calendar close
890923
});
891924
});
892925
} else {
@@ -942,9 +975,9 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
942975
private updateInputs(): void {
943976
const start = this.projectedInputs?.find(i => i instanceof IgxDateRangeStartComponent) as IgxDateRangeStartComponent;
944977
const end = this.projectedInputs?.find(i => i instanceof IgxDateRangeEndComponent) as IgxDateRangeEndComponent;
945-
if (start && end && this.value) {
946-
start.updateInputValue(this.value.start);
947-
end.updateInputValue(this.value.end);
978+
if (start && end) {
979+
start.updateInputValue(this.value?.start ?? null);
980+
end.updateInputValue(this.value?.end ?? null);
948981
}
949982
}
950983
}

0 commit comments

Comments
 (0)