Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit b7c56c2

Browse files
committed
feat(modal): add container option
feat(modal): add container option
1 parent 3144633 commit b7c56c2

File tree

3 files changed

+59
-9
lines changed

3 files changed

+59
-9
lines changed

Diff for: src/modal/docs/readme.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ The `$uibModal` service has only one method: `open(options)` where available opt
1919
* `windowTemplateUrl` - a path to a template overriding modal's window template
2020
* `size` - optional suffix of modal window class. The value used is appended to the `modal-` class, i.e. a value of `sm` gives `modal-sm`
2121
* `openedClass` - class added to the `body` element when the modal is opened. Defaults to `modal-open`
22+
* `container` - Appends the modal to a specific element. container must be an `angular.element`. Defaults to `body` element. Example: `container: $document.find('aside')`.
2223

2324
Global defaults may be set for `$uibModal` via `$uibModalProvider.options`.
2425

Diff for: src/modal/modal.js

+16-9
Original file line numberDiff line numberDiff line change
@@ -276,16 +276,16 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
276276
});
277277

278278
function removeModalWindow(modalInstance, elementToReceiveFocus) {
279-
var body = $document.find('body').eq(0);
280279
var modalWindow = openedWindows.get(modalInstance).value;
280+
var container = $document.find(modalWindow.container).eq(0);
281281

282282
//clean up the stack
283283
openedWindows.remove(modalInstance);
284284

285285
removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {
286286
var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
287287
openedClasses.remove(modalBodyClass, modalInstance);
288-
body.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass));
288+
container.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass));
289289
toggleTopWindowClass(true);
290290
});
291291
checkRemoveBackdrop();
@@ -294,7 +294,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
294294
if (elementToReceiveFocus && elementToReceiveFocus.focus) {
295295
elementToReceiveFocus.focus();
296296
} else {
297-
body.focus();
297+
container.focus();
298298
}
299299
}
300300

@@ -413,14 +413,19 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
413413
backdrop: modal.backdrop,
414414
keyboard: modal.keyboard,
415415
openedClass: modal.openedClass,
416-
windowTopClass: modal.windowTopClass
416+
windowTopClass: modal.windowTopClass,
417+
container: modal.container
417418
});
418419

419420
openedClasses.put(modalBodyClass, modalInstance);
420421

421-
var body = $document.find('body').eq(0),
422+
var container = $document.find(modal.container).eq(0),
422423
currBackdropIndex = backdropIndex();
423424

425+
if (!container.length) {
426+
throw new Error('Container not found. Make sure that the container passed is in DOM.');
427+
}
428+
424429
if (currBackdropIndex >= 0 && !backdropDomEl) {
425430
backdropScope = $rootScope.$new(true);
426431
backdropScope.index = currBackdropIndex;
@@ -430,7 +435,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
430435
angularBackgroundDomEl.attr('modal-animation', 'true');
431436
}
432437
backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);
433-
body.append(backdropDomEl);
438+
container.append(backdropDomEl);
434439
}
435440

436441
var angularDomEl = angular.element('<div uib-modal-window="modal-window"></div>');
@@ -449,8 +454,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
449454
var modalDomEl = $compile(angularDomEl)(modal.scope);
450455
openedWindows.top().value.modalDomEl = modalDomEl;
451456
openedWindows.top().value.modalOpener = modalOpener;
452-
body.append(modalDomEl);
453-
body.addClass(modalBodyClass);
457+
container.append(modalDomEl);
458+
container.addClass(modalBodyClass);
454459

455460
$modalStack.clearFocusListCache();
456461
};
@@ -603,6 +608,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
603608
//merge and clean up options
604609
modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
605610
modalOptions.resolve = modalOptions.resolve || {};
611+
modalOptions.container = modalOptions.container || 'body';
606612

607613
//verify options
608614
if (!modalOptions.template && !modalOptions.templateUrl) {
@@ -669,7 +675,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
669675
windowClass: modalOptions.windowClass,
670676
windowTemplateUrl: modalOptions.windowTemplateUrl,
671677
size: modalOptions.size,
672-
openedClass: modalOptions.openedClass
678+
openedClass: modalOptions.openedClass,
679+
container: modalOptions.container
673680
});
674681
modalOpenedDeferred.resolve(true);
675682

Diff for: src/modal/test/modal.spec.js

+42
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,48 @@ describe('$uibModal', function () {
833833
expect($document.find('.modal-backdrop')).not.toHaveClass('fade');
834834
});
835835
});
836+
837+
describe('container', function() {
838+
it('should be added to body by default', function() {
839+
var modal = open({template: '<div>Content</div>'});
840+
841+
expect($document).toHaveModalsOpen(1);
842+
expect($document).toHaveModalOpenWithContent('Content', 'div');
843+
});
844+
845+
it('should not be added to body if container is passed', function() {
846+
var element = angular.element('<section>Some content</section>');
847+
angular.element(document.body).append(element);
848+
849+
var modal = open({template: '<div>Content</div>', container: element});
850+
851+
expect($document).not.toHaveModalOpenWithContent('Content', 'div');
852+
});
853+
854+
it('should be added to container if container is passed', function() {
855+
var element = angular.element('<section>Some content</section>');
856+
angular.element(document.body).append(element);
857+
858+
expect($document.find('section').children('div.modal').length).toBe(0);
859+
open({template: '<div>Content</div>', container: element});
860+
expect($document.find('section').children('div.modal').length).toBe(1);
861+
});
862+
863+
it('should throw error if container is not found', function() {
864+
expect(function(){
865+
open({template: '<div>Content</div>', container: $document.find('aside')});
866+
}).toThrow(new Error('Container not found. Make sure that the container passed is in DOM.'));
867+
});
868+
869+
it('should be removed from container when dismissed', function() {
870+
var modal = open({template: '<div>Content</div>'});
871+
872+
expect($document).toHaveModalsOpen(1);
873+
874+
dismiss(modal);
875+
expect($document).toHaveModalsOpen(0);
876+
});
877+
});
836878

837879
describe('openedClass', function() {
838880
var body;

0 commit comments

Comments
 (0)