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

Commit e28cced

Browse files
committed
feat(modal): support requiring from parent directive
- Add support for requiring from parent directive of element being appended to Closes #3765 Closes #4844
1 parent ee7ab9f commit e28cced

File tree

2 files changed

+83
-26
lines changed

2 files changed

+83
-26
lines changed

src/modal/modal.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,9 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
219219
};
220220
})
221221

222-
.factory('$uibModalStack', ['$animate', '$animateCss', '$timeout', '$document',
222+
.factory('$uibModalStack', ['$animate', '$animateCss', '$document',
223223
'$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap',
224-
function($animate, $animateCss, $timeout, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap) {
224+
function($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap) {
225225
var OPENED_MODAL_CLASS = 'modal-open';
226226

227227
var backdropDomEl, backdropScope;
@@ -430,14 +430,15 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
430430
angularDomEl.attr('modal-animation', 'true');
431431
}
432432

433-
var modalDomEl = $compile(angularDomEl)(modal.scope);
434-
openedWindows.top().value.modalDomEl = modalDomEl;
435-
openedWindows.top().value.modalOpener = modalOpener;
436-
$animate.enter(modalDomEl, appendToElement)
433+
$animate.enter(angularDomEl, appendToElement)
437434
.then(function() {
435+
$compile(angularDomEl)(modal.scope);
438436
$animate.addClass(appendToElement, modalBodyClass);
439437
});
440438

439+
openedWindows.top().value.modalDomEl = angularDomEl;
440+
openedWindows.top().value.modalOpener = modalOpener;
441+
441442
$modalStack.clearFocusListCache();
442443
};
443444

src/modal/test/modal.spec.js

+76-20
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,23 @@ describe('$uibModal', function () {
66
beforeEach(module('ui.bootstrap.modal'));
77
beforeEach(module('uib/template/modal/backdrop.html'));
88
beforeEach(module('uib/template/modal/window.html'));
9-
beforeEach(module(function(_$controllerProvider_, _$uibModalProvider_){
9+
beforeEach(module(function(_$controllerProvider_, _$uibModalProvider_, $compileProvider) {
1010
$controllerProvider = _$controllerProvider_;
1111
$uibModalProvider = _$uibModalProvider_;
12+
$compileProvider.directive('parentDirective', function() {
13+
return {
14+
controller: function() {
15+
this.text = 'foo';
16+
}
17+
};
18+
}).directive('childDirective', function() {
19+
return {
20+
require: '^parentDirective',
21+
link: function(scope, elem, attrs, ctrl) {
22+
scope.text = ctrl.text;
23+
}
24+
};
25+
});
1226
}));
1327

1428
beforeEach(inject(function(_$animate_, _$rootScope_, _$document_, _$compile_, _$templateCache_, _$timeout_, _$q_, _$uibModal_, _$uibModalStack_) {
@@ -144,10 +158,12 @@ describe('$uibModal', function () {
144158
element.trigger(e);
145159
}
146160

147-
function open(modalOptions) {
161+
function open(modalOptions, noFlush) {
148162
var modal = $uibModal.open(modalOptions);
149163
$rootScope.$digest();
150-
$timeout.flush(0);
164+
if (!noFlush) {
165+
$animate.flush();
166+
}
151167
return modal;
152168
}
153169

@@ -376,9 +392,8 @@ describe('$uibModal', function () {
376392

377393
it('should expose a promise linked to the templateUrl / resolve promises and reject it if needed', function() {
378394
var modal = open({template: '<div>Content</div>', resolve: {
379-
ok: function() {return $q.reject('ko');}
380-
}}
381-
);
395+
ok: function() {return $q.reject('ko');}
396+
}}, true);
382397
expect(modal.opened).toBeRejectedWith('ko');
383398
});
384399

@@ -633,10 +648,11 @@ describe('$uibModal', function () {
633648
value: function() {
634649
return $timeout(function() { return 'Promise'; }, 100);
635650
}
636-
}));
651+
}), true);
637652
expect($document).toHaveModalsOpen(0);
638653

639654
$timeout.flush();
655+
$animate.flush();
640656
expect($document).toHaveModalOpenWithContent('Promise', 'div');
641657
});
642658

@@ -647,7 +663,7 @@ describe('$uibModal', function () {
647663
value: function() {
648664
return deferred.promise;
649665
}
650-
}));
666+
}), true);
651667
expect($document).toHaveModalsOpen(0);
652668

653669
deferred.reject('error in test');
@@ -858,6 +874,8 @@ describe('$uibModal', function () {
858874
expect($document.find('section').children('div.modal').length).toBe(0);
859875
open({template: '<div>Content</div>', appendTo: element});
860876
expect($document.find('section').children('div.modal').length).toBe(1);
877+
878+
element.remove();
861879
});
862880

863881
it('should throw error if appendTo element is not found', function() {
@@ -874,6 +892,17 @@ describe('$uibModal', function () {
874892
dismiss(modal);
875893
expect($document).toHaveModalsOpen(0);
876894
});
895+
896+
it('should allow requiring parent directive from appendTo target', function() {
897+
var element = $compile('<section parent-directive>Some content</section>')($rootScope);
898+
angular.element(document.body).append(element);
899+
900+
open({template: '<div child-directive>{{text}}</div>', appendTo: element});
901+
$animate.flush();
902+
expect($document.find('[child-directive]').text()).toBe('foo');
903+
904+
element.remove();
905+
});
877906
});
878907

879908
describe('openedClass', function() {
@@ -1008,7 +1037,7 @@ describe('$uibModal', function () {
10081037
expect($document).toHaveModalsOpen(2);
10091038
});
10101039

1011-
it('multiple modals should not interfere with default options', function() {
1040+
it('should not interfere with default options', function() {
10121041
var modal1 = open({template: '<div>Modal1</div>', backdrop: false});
10131042
var modal2 = open({template: '<div>Modal2</div>'});
10141043
$rootScope.$digest();
@@ -1084,7 +1113,7 @@ describe('$uibModal', function () {
10841113
} else {
10851114
expected += i;
10861115
}
1087-
ds[x] = {index:i, deferred:$q.defer(), reject:reject};
1116+
ds[x] = {index: i, deferred: $q.defer(), reject: reject};
10881117

10891118
var scope = $rootScope.$new();
10901119
scope.index = i;
@@ -1094,17 +1123,17 @@ describe('$uibModal', function () {
10941123
resolve: {
10951124
x: function() { return ds[x].deferred.promise; }
10961125
}
1097-
}).opened.then(function() {
1126+
}, true).opened.then(function() {
10981127
expect($uibModalStack.getTop().value.modalScope.index).toEqual(i);
10991128
actual += i;
11001129
});
11011130
});
11021131

11031132
angular.forEach(ds, function(d, i) {
11041133
if (d.reject) {
1105-
d.deferred.reject('rejected:' + d.index );
1134+
d.deferred.reject('rejected:' + d.index);
11061135
} else {
1107-
d.deferred.resolve('resolved:' + d.index );
1136+
d.deferred.resolve('resolved:' + d.index);
11081137
}
11091138
$rootScope.$digest();
11101139
});
@@ -1138,13 +1167,39 @@ describe('$uibModal', function () {
11381167
_permute(0);
11391168
}
11401169

1141-
permute(2, function(a) { test(a); });
1142-
permute(2, function(a) { test(a.map(function(x, i) { return {reject:x}; })); });
1143-
permute(2, function(a) { test(a.map(function(x, i) { return i === 0 ? {reject:x} : x; })); });
1144-
permute(3, function(a) { test(a); });
1145-
permute(3, function(a) { test(a.map(function(x, i) { return {reject:x}; })); });
1146-
permute(3, function(a) { test(a.map(function(x, i) { return i === 0 ? {reject:x} : x; })); });
1147-
permute(3, function(a) { test(a.map(function(x, i) { return i === 1 ? {reject:x} : x; })); });
1170+
permute(2, function(a) {
1171+
test(a);
1172+
});
1173+
permute(2, function(a) {
1174+
test(a.map(function(x, i) {
1175+
return {reject:x};
1176+
}));
1177+
});
1178+
permute(2, function(a) {
1179+
test(a.map(function(x, i) {
1180+
return i === 0 ? {reject: x} : x;
1181+
}));
1182+
});
1183+
permute(3, function(a) {
1184+
test(a);
1185+
});
1186+
permute(3, function(a) {
1187+
test(a.map(function(x, i) {
1188+
return {reject: x};
1189+
}));
1190+
});
1191+
permute(3, function(a) {
1192+
test(a.map(function(x, i) {
1193+
return i === 0 ? {reject: x} : x;
1194+
}));
1195+
});
1196+
permute(3, function(a) {
1197+
test(a.map(function(x, i) {
1198+
return i === 1 ? {reject: x} : x;
1199+
}));
1200+
});
1201+
1202+
$animate.flush();
11481203
});
11491204

11501205
it('should have top class only on top window', function () {
@@ -1213,6 +1268,7 @@ describe('$uibModal', function () {
12131268
var called;
12141269

12151270
called = false;
1271+
12161272
close(open({
12171273
template: '<div>content</div>',
12181274
controller: function($scope) {

0 commit comments

Comments
 (0)