From a5420032d56214901f7b9a9aca6562219ba59620 Mon Sep 17 00:00:00 2001 From: Sergey Andrievskiy Date: Wed, 13 Mar 2019 16:59:14 +0300 Subject: [PATCH 1/3] fix(select): update selected after cd run is finished --- .../theme/components/select/select.component.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/framework/theme/components/select/select.component.ts b/src/framework/theme/components/select/select.component.ts index a251169221..6f5b47ede8 100644 --- a/src/framework/theme/components/select/select.component.ts +++ b/src/framework/theme/components/select/select.component.ts @@ -321,6 +321,16 @@ export class NbSelectComponent implements OnInit, AfterViewInit, AfterContent this.createOverlay(); } + ngAfterContentInit() { + if (this.queue) { + // Call 'writeValue' when current change detection run is finished. + // When writing is finished, change detection starts again, since + // microtasks queue is empty. + // Prevents ExpressionChangedAfterItHasBeenCheckedError. + Promise.resolve().then(() => this.writeValue(this.queue)); + } + } + ngAfterViewInit() { this.triggerStrategy = this.createTriggerStrategy(); @@ -329,13 +339,6 @@ export class NbSelectComponent implements OnInit, AfterViewInit, AfterContent this.subscribeOnSelectionChange(); } - ngAfterContentInit() { - if (this.queue) { - this.writeValue(this.queue); - this.cd.detectChanges(); - } - } - ngOnDestroy() { this.alive = false; From be46ce4c4422c77421a243824b8485d83ca403c4 Mon Sep 17 00:00:00 2001 From: Sergey Andrievskiy Date: Wed, 13 Mar 2019 17:38:09 +0300 Subject: [PATCH 2/3] feat(select): clear queue after value was written --- src/framework/theme/components/select/select.component.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/framework/theme/components/select/select.component.ts b/src/framework/theme/components/select/select.component.ts index 6f5b47ede8..042701027f 100644 --- a/src/framework/theme/components/select/select.component.ts +++ b/src/framework/theme/components/select/select.component.ts @@ -327,7 +327,10 @@ export class NbSelectComponent implements OnInit, AfterViewInit, AfterContent // When writing is finished, change detection starts again, since // microtasks queue is empty. // Prevents ExpressionChangedAfterItHasBeenCheckedError. - Promise.resolve().then(() => this.writeValue(this.queue)); + Promise.resolve().then(() => { + this.writeValue(this.queue); + this.queue = null; + }); } } From 9e9594830f14a9850e5e62ffac0816dffa15077c Mon Sep 17 00:00:00 2001 From: Sergey Andrievskiy Date: Thu, 14 Mar 2019 15:35:45 +0300 Subject: [PATCH 3/3] test(select): check select with initially selected value --- .../theme/components/select/select.spec.ts | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/framework/theme/components/select/select.spec.ts b/src/framework/theme/components/select/select.spec.ts index ad746c4018..833206832b 100644 --- a/src/framework/theme/components/select/select.spec.ts +++ b/src/framework/theme/components/select/select.spec.ts @@ -5,7 +5,7 @@ */ import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, flush, TestBed } from '@angular/core/testing'; import { NbSelectModule } from './select.module'; import { NbThemeModule } from '../../theme.module'; @@ -75,6 +75,24 @@ export class NbSelectTestComponent { groups = TEST_GROUPS; } +@Component({ + template: ` + + + + {{ option }} + + + + `, +}) +export class NbSelectWithInitiallySelectedOptionComponent { + @Input() selected = 1; + @Input() options = [ 1, 2, 3 ]; + + @ViewChild(NbSelectComponent) select: NbSelectComponent; +} + describe('Component: NbSelectComponent', () => { let fixture: ComponentFixture; let overlayContainerService: NbOverlayContainerAdapter; @@ -96,7 +114,7 @@ describe('Component: NbSelectComponent', () => { NbLayoutModule, NbSelectModule, ], - declarations: [NbSelectTestComponent], + declarations: [ NbSelectTestComponent, NbSelectWithInitiallySelectedOptionComponent ], }); fixture = TestBed.createComponent(NbSelectTestComponent); @@ -221,4 +239,15 @@ describe('Component: NbSelectComponent', () => { expect(button.textContent).toContain('1 noitpO'); }) }); + + it('should select initially specified value without errors', fakeAsync(() => { + const selectFixture = TestBed.createComponent(NbSelectWithInitiallySelectedOptionComponent); + selectFixture.detectChanges(); + flush(); + + const selectedOption = selectFixture.componentInstance.select.options.find(o => o.selected); + expect(selectedOption.value).toEqual(selectFixture.componentInstance.selected); + const selectButton = selectFixture.nativeElement.querySelector('nb-select button') as HTMLElement; + expect(selectButton.textContent).toEqual(selectedOption.value.toString()); + })); });