-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(modal): don't close popup on ESC when closing nested components (#…
…3384) Fixes an issue for datepicker, typeahead, dropdown inside the modal. When these components are closed on ESC, now modal stays open. Fixes #3358
- Loading branch information
1 parent
d8812b9
commit 75f0966
Showing
12 changed files
with
242 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
e2e-app/src/app/modal/nesting/modal-nesting.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<h3>Modal nesting tests</h3> | ||
|
||
<ng-template #t let-modal> | ||
<div class="modal-header"> | ||
<h4 class="modal-title">Modal with nested popups</h4> | ||
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss()"> | ||
<span aria-hidden="true">×</span> | ||
</button> | ||
</div> | ||
<div class="modal-body"> | ||
<form> | ||
<!-- datepicker --> | ||
<div class="form-group"> | ||
<label for="datepicker">Datepicker</label> | ||
<div class="input-group"> | ||
<input id="datepicker" class="form-control" placeholder="yyyy-mm-dd" name="dp" | ||
ngbDatepicker #dp="ngbDatepicker" [startDate]="{year: 2018, month: 1}"> | ||
<div class="input-group-append"> | ||
<button class="btn btn-outline-secondary" id="datepicker-button" (click)="dp.toggle()" type="button">Open</button> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<!-- dropdown --> | ||
<div class="form-group"> | ||
<label for="dropdown">Typeahead</label> | ||
<div class="input-group"> | ||
<div ngbDropdown class="d-inline-block"> | ||
<button class="btn btn-outline-primary" id="dropdown" ngbDropdownToggle>Toggle dropdown</button> | ||
<div ngbDropdownMenu aria-labelledby="dropdownBasic1"> | ||
<button ngbDropdownItem>Action - 1</button> | ||
<button ngbDropdownItem>Another Action</button> | ||
<button ngbDropdownItem>Something else is here</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<!-- typeahead --> | ||
<div class="form-group"> | ||
<label for="typeahead">Typeahead</label> | ||
<div class="input-group"> | ||
<input id="typeahead" type="text" name="tphd" class="form-control" [ngbTypeahead]="search"/> | ||
</div> | ||
</div> | ||
</form> | ||
</div> | ||
</ng-template> | ||
|
||
<button class="btn btn-outline-secondary ml-2" type="button" id="open-modal" (click)="openModal(t)">Open Modal</button> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import {Component, TemplateRef} from '@angular/core'; | ||
import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; | ||
import {Observable} from 'rxjs'; | ||
import {map} from 'rxjs/operators'; | ||
|
||
@Component({templateUrl: './modal-nesting.component.html'}) | ||
export class ModalNestingComponent { | ||
constructor(private modalService: NgbModal) {} | ||
|
||
openModal(content: TemplateRef<any>) { this.modalService.open(content); } | ||
|
||
search = (text$: Observable<string>) => text$.pipe(map(() => ['one', 'two', 'three'])); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import {Key} from 'protractor'; | ||
import {expectFocused, expectNoOpenModals, openUrl, sendKey} from '../../tools.po'; | ||
import {ModalNestingPage} from './modal-nesting.po'; | ||
import {DatepickerPage} from '../../datepicker/datepicker.po'; | ||
import {DropdownPage} from '../../dropdown/dropdown.po'; | ||
import {TypeaheadPage} from '../../typeahead/typeahead.po'; | ||
|
||
describe('Modal nested components', () => { | ||
let page: ModalNestingPage; | ||
let datepickerPage: DatepickerPage; | ||
let dropdownPage: DropdownPage; | ||
let typeaheadPage: TypeaheadPage; | ||
|
||
beforeAll(() => { | ||
page = new ModalNestingPage(); | ||
datepickerPage = new DatepickerPage(); | ||
dropdownPage = new DropdownPage(); | ||
typeaheadPage = new TypeaheadPage(); | ||
}); | ||
|
||
beforeEach(async() => await openUrl('modal/nesting')); | ||
|
||
afterEach(async() => { await expectNoOpenModals(); }); | ||
|
||
it('should close only datepicker, then modal on ESC', async() => { | ||
await page.openModal(); | ||
|
||
// open datepicker | ||
await page.getDatepickerButton().click(); | ||
expect(await datepickerPage.getDatepicker().isPresent()).toBeTruthy(`Datepicker should be opened`); | ||
await expectFocused(await datepickerPage.getDayElement(new Date(2018, 0, 1)), `01 JAN 2018 should be focused`); | ||
|
||
// close datepicker | ||
await sendKey(Key.ESCAPE); | ||
expect(await datepickerPage.getDatepicker().isPresent()).toBeFalsy(`Datepicker should be closed`); | ||
await expectFocused(await page.getDatepickerButton(), `Datepicker open button should be focused`); | ||
expect(await page.getModal().isPresent()).toBeTruthy(`Modal should stay opened`); | ||
|
||
// close modal | ||
await sendKey(Key.ESCAPE); | ||
}); | ||
|
||
it('should close only dropdown, then modal on ESC', async() => { | ||
await page.openModal(); | ||
|
||
// open dropdown | ||
await page.getDropdownButton().click(); | ||
const dropdown = dropdownPage.getDropdown(); | ||
expect(await dropdownPage.isOpened(dropdown)).toBeTruthy(`Dropdown should be opened`); | ||
await expectFocused(page.getDropdownButton(), `Dropdown button should be focused`); | ||
|
||
// close dropdown | ||
await sendKey(Key.ESCAPE); | ||
expect(await dropdownPage.isOpened(dropdown)).toBeFalsy(`Dropdown should be closed`); | ||
await expectFocused(await page.getDropdownButton(), `Dropdown open button should be focused`); | ||
expect(await page.getModal().isPresent()).toBeTruthy(`Modal should stay opened`); | ||
|
||
// close modal | ||
await sendKey(Key.ESCAPE); | ||
}); | ||
|
||
it('should close only typeahead, then modal on ESC', async() => { | ||
await page.openModal(); | ||
|
||
// open typeahead | ||
await page.getTypeaheadInput().click(); | ||
await sendKey(Key.SPACE); | ||
expect(await typeaheadPage.getDropdown().isPresent()).toBeTruthy(`Typeahead should be opened`); | ||
await expectFocused(page.getTypeaheadInput(), `Typeahead input should be focused`); | ||
|
||
// close dropdown | ||
await sendKey(Key.ESCAPE); | ||
expect(await typeaheadPage.getDropdown().isPresent()).toBeFalsy(`Typeahead should be closed`); | ||
await expectFocused(page.getTypeaheadInput(), `Typeahead input should be focused`); | ||
expect(await page.getModal().isPresent()).toBeTruthy(`Modal should stay opened`); | ||
|
||
// close modal | ||
await sendKey(Key.ESCAPE); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import {$} from 'protractor'; | ||
|
||
export class ModalNestingPage { | ||
getModal(selector = 'ngb-modal-window') { return $(selector); } | ||
|
||
getDatepickerButton() { return $('#datepicker-button'); } | ||
|
||
getDropdownButton() { return $('#dropdown'); } | ||
|
||
getTypeaheadInput() { return $('#typeahead'); } | ||
|
||
async openModal() { | ||
await $(`#open-modal`).click(); | ||
const modal = this.getModal(); | ||
expect(await modal.isPresent()).toBeTruthy(`A modal should have been opened`); | ||
return modal; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.