Skip to content

Commit fc86df8

Browse files
authored
Merge pull request #9837 from IgniteUI/bpenkov/date-range-disabled-onpush
Update disabled with CD strategy OnPush
2 parents 7c923e8 + f0bac29 commit fc86df8

File tree

3 files changed

+99
-12
lines changed

3 files changed

+99
-12
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<ng-template #defTemplate>
2727
<igx-input-group [type]="this.type" [displayDensity]="this.displayDensity" (click)="this.open()">
2828
<!-- only set mask placeholder when empty, otherwise input group might use it as label if none is set -->
29-
<input #singleInput igxInput type="text" readonly [placeholder]="this.value ? '' : singleInputFormat"
29+
<input #singleInput igxInput type="text" readonly [disabled]="this.disabled" [placeholder]="this.value ? '' : singleInputFormat"
3030
role="combobox" aria-haspopup="grid" [attr.aria-expanded]="!this.collapsed"
3131
[attr.aria-labelledby]="this.label?.id"
3232
[value]="this.value | dateRange: this.appliedFormat : this.locale : this.formatter" />

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

+88-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ComponentFixture, TestBed, fakeAsync, tick, waitForAsync, flush } from '@angular/core/testing';
2-
import { Component, OnInit, ViewChild, DebugElement } from '@angular/core';
2+
import { Component, OnInit, ViewChild, DebugElement, ChangeDetectionStrategy } from '@angular/core';
33
import { IgxInputGroupModule } from '../input-group/public_api';
44
import { PickerInteractionMode } from '../date-common/types';
55
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
@@ -21,6 +21,8 @@ import { AnimationMetadata, AnimationOptions } from '@angular/animations';
2121
import { IgxPickersCommonModule } from '../date-common/public_api';
2222
import { IgxCalendarContainerComponent, IgxCalendarContainerModule } from '../date-common/calendar-container/calendar-container.component';
2323
import { IgxCalendarComponent } from '../calendar/public_api';
24+
import { Subject } from 'rxjs';
25+
import { CommonModule } from '@angular/common';
2426

2527
// The number of milliseconds in one day
2628
const ONE_DAY = 1000 * 60 * 60 * 24;
@@ -224,7 +226,7 @@ describe('IgxDateRangePicker', () => {
224226
});
225227

226228
it('should validate correctly minValue and maxValue', () => {
227-
const dateRange = new IgxDateRangePickerComponent(elementRef, null, platform, mockInjector, null, null);
229+
const dateRange = new IgxDateRangePickerComponent(elementRef, null, platform, mockInjector, null, null, null);
228230
dateRange.ngOnInit();
229231

230232
// dateRange.calendar = calendar;
@@ -249,7 +251,7 @@ describe('IgxDateRangePicker', () => {
249251
});
250252

251253
it('should disable calendar dates when min and/or max values as dates are provided', () => {
252-
const dateRange = new IgxDateRangePickerComponent(elementRef, 'en-US', platform, mockInjector, ngModuleRef, overlay);
254+
const dateRange = new IgxDateRangePickerComponent(elementRef, 'en-US', platform, mockInjector, ngModuleRef, null, overlay);
253255
dateRange.ngOnInit();
254256

255257
spyOnProperty((dateRange as any), 'calendar').and.returnValue(mockCalendar);
@@ -275,7 +277,7 @@ describe('IgxDateRangePicker', () => {
275277
});
276278

277279
it('should disable calendar dates when min and/or max values as strings are provided', fakeAsync(() => {
278-
const dateRange = new IgxDateRangePickerComponent(elementRef, null, platform, mockInjector, null, null);
280+
const dateRange = new IgxDateRangePickerComponent(elementRef, null, platform, mockInjector, null, null, null);
279281
dateRange.ngOnInit();
280282

281283
spyOnProperty((dateRange as any), 'calendar').and.returnValue(mockCalendar);
@@ -332,17 +334,19 @@ describe('IgxDateRangePicker', () => {
332334
TestBed.configureTestingModule({
333335
declarations: [
334336
DateRangeTestComponent,
335-
DateRangeDefaultComponent
337+
DateRangeDefaultComponent,
338+
DateRangeDisabledComponent
336339
],
337340
imports: [
341+
CommonModule,
338342
IgxDateRangePickerModule,
339343
IgxDateTimeEditorModule,
340344
IgxInputGroupModule,
341345
IgxIconModule,
342346
FormsModule,
343347
NoopAnimationsModule,
344348
IgxPickersCommonModule,
345-
IgxCalendarContainerModule,
349+
IgxCalendarContainerModule
346350
]
347351
})
348352
.compileComponents();
@@ -732,6 +736,28 @@ describe('IgxDateRangePicker', () => {
732736
fixture.detectChanges();
733737
expect(fixture.componentInstance.dateRange.collapsed).toBeTruthy();
734738
}));
739+
740+
it('should properly set/update disabled when ChangeDetectionStrategy.OnPush is used', fakeAsync(() => {
741+
const testFixture = TestBed
742+
.createComponent(DateRangeDisabledComponent) as ComponentFixture<DateRangeDisabledComponent>;
743+
testFixture.detectChanges();
744+
dateRange = testFixture.componentInstance.dateRange;
745+
const disabled$ = testFixture.componentInstance.disabled$;
746+
747+
disabled$.next(true);
748+
testFixture.detectChanges();
749+
expect(dateRange.inputDirective.disabled).toBeTrue();
750+
751+
disabled$.next(false);
752+
testFixture.detectChanges();
753+
expect(dateRange.inputDirective.disabled).toBeFalse();
754+
755+
disabled$.next(true);
756+
testFixture.detectChanges();
757+
expect(dateRange.inputDirective.disabled).toBeTrue();
758+
759+
disabled$.complete();
760+
}));
735761
});
736762

737763
describe('Two Inputs', () => {
@@ -743,9 +769,12 @@ describe('IgxDateRangePicker', () => {
743769
declarations: [
744770
DateRangeTestComponent,
745771
DateRangeTwoInputsTestComponent,
746-
DateRangeTwoInputsNgModelTestComponent
772+
DateRangeTwoInputsNgModelTestComponent,
773+
DateRangeDisabledComponent,
774+
DateRangeTwoInputsDisabledComponent
747775
],
748776
imports: [
777+
CommonModule,
749778
IgxDateRangePickerModule,
750779
IgxDateTimeEditorModule,
751780
IgxPickersCommonModule,
@@ -1116,6 +1145,31 @@ describe('IgxDateRangePicker', () => {
11161145
expect(fixture.componentInstance.dateRange.collapsed).toBeTruthy();
11171146
}));
11181147

1148+
it('should properly set/update disabled when ChangeDetectionStrategy.OnPush is used', fakeAsync(() => {
1149+
const testFixture = TestBed
1150+
.createComponent(DateRangeTwoInputsDisabledComponent) as ComponentFixture<DateRangeTwoInputsDisabledComponent>;
1151+
testFixture.detectChanges();
1152+
dateRange = testFixture.componentInstance.dateRange;
1153+
const disabled$ = testFixture.componentInstance.disabled$;
1154+
1155+
disabled$.next(true);
1156+
testFixture.detectChanges();
1157+
expect(dateRange.projectedInputs.first.inputDirective.disabled).toBeTrue();
1158+
expect(dateRange.projectedInputs.last.inputDirective.disabled).toBeTrue();
1159+
1160+
disabled$.next(false);
1161+
testFixture.detectChanges();
1162+
expect(dateRange.projectedInputs.first.inputDirective.disabled).toBeFalse();
1163+
expect(dateRange.projectedInputs.last.disabled).toBeFalse();
1164+
1165+
disabled$.next(true);
1166+
testFixture.detectChanges();
1167+
expect(dateRange.projectedInputs.first.inputDirective.disabled).toBeTrue();
1168+
expect(dateRange.projectedInputs.last.inputDirective.disabled).toBeTrue();
1169+
1170+
disabled$.complete();
1171+
}));
1172+
11191173
describe('Data binding', () => {
11201174
it('should properly update component value with ngModel bound to projected inputs - #7353', fakeAsync(() => {
11211175
fixture = TestBed.createComponent(DateRangeTwoInputsNgModelTestComponent);
@@ -1417,3 +1471,30 @@ export class DateRangeCustomComponent extends DateRangeTestComponent {
14171471
export class DateRangeTemplatesComponent extends DateRangeTestComponent {
14181472
public range;
14191473
}
1474+
1475+
@Component({
1476+
template: `<igx-date-range-picker [disabled]="(disabled$ | async) === true"></igx-date-range-picker>`,
1477+
changeDetection: ChangeDetectionStrategy.OnPush
1478+
})
1479+
export class DateRangeDisabledComponent extends DateRangeTestComponent {
1480+
public disabled$ = new Subject<boolean>();
1481+
1482+
constructor() {
1483+
super();
1484+
this.disabled$.subscribe({ next: (v) => v });
1485+
}
1486+
}
1487+
1488+
@Component({
1489+
template: `
1490+
<igx-date-range-picker [disabled]="(disabled$ | async) === true">
1491+
<igx-date-range-start>
1492+
<input igxInput igxDateTimeEditor>
1493+
</igx-date-range-start>
1494+
<igx-date-range-end>
1495+
<input igxInput igxDateTimeEditor>
1496+
</igx-date-range-end>
1497+
</igx-date-range-picker>`,
1498+
changeDetection: ChangeDetectionStrategy.OnPush
1499+
})
1500+
export class DateRangeTwoInputsDisabledComponent extends DateRangeDisabledComponent { }

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

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
AfterViewInit, Component, ContentChild, ContentChildren, ElementRef,
2+
AfterViewInit, ChangeDetectorRef, Component, ContentChild, ContentChildren, ElementRef,
33
EventEmitter, HostBinding, HostListener, Inject, Injector, Input, LOCALE_ID,
44
NgModuleRef,
55
OnChanges, OnDestroy, OnInit, Optional, Output, QueryList,
@@ -447,6 +447,7 @@ export class IgxDateRangePickerComponent extends PickerBaseDirective
447447
protected platform: PlatformUtil,
448448
private _injector: Injector,
449449
private _moduleRef: NgModuleRef<any>,
450+
private _cdr: ChangeDetectorRef,
450451
@Inject(IgxOverlayService) private _overlayService: IgxOverlayService,
451452
@Optional() @Inject(DisplayDensityToken) protected _displayDensityOptions?: IDisplayDensityOptions,
452453
@Optional() @Inject(IGX_INPUT_GROUP_TYPE) protected _inputGroupType?: IgxInputGroupType) {
@@ -632,6 +633,14 @@ export class IgxDateRangePickerComponent extends PickerBaseDirective
632633
this.updateDisabledState();
633634
this.initialSetValue();
634635
this.updateInputs();
636+
// B.P. 07 July 2021 - IgxDateRangePicker not showing initial disabled state with ChangeDetectionStrategy.OnPush #9776
637+
/**
638+
* if disabled is placed on the range picker element and there are projected inputs
639+
* run change detection since igxInput will initially set the projected inputs' disabled to false
640+
*/
641+
if (this.hasProjectedInputs && this.disabled) {
642+
this._cdr.markForCheck();
643+
}
635644
});
636645
this.updateDisplayFormat();
637646
this.updateInputFormat();
@@ -791,9 +800,6 @@ export class IgxDateRangePickerComponent extends PickerBaseDirective
791800
end.inputDirective.disabled = this.disabled;
792801
return;
793802
}
794-
if (this.inputDirective) {
795-
this.inputDirective.disabled = this.disabled;
796-
}
797803
}
798804

799805
private getInputState(focused: boolean): IgxInputState {

0 commit comments

Comments
 (0)