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

Commit

Permalink
feat(modal): support requiring from parent directive
Browse files Browse the repository at this point in the history
- Add support for requiring from parent directive of element being
  appended to

Closes #3765
Closes #4844
  • Loading branch information
wesleycho committed Nov 9, 2015
1 parent ee7ab9f commit e28cced
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 26 deletions.
13 changes: 7 additions & 6 deletions src/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,9 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
};
})

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

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

var modalDomEl = $compile(angularDomEl)(modal.scope);
openedWindows.top().value.modalDomEl = modalDomEl;
openedWindows.top().value.modalOpener = modalOpener;
$animate.enter(modalDomEl, appendToElement)
$animate.enter(angularDomEl, appendToElement)
.then(function() {
$compile(angularDomEl)(modal.scope);
$animate.addClass(appendToElement, modalBodyClass);
});

openedWindows.top().value.modalDomEl = angularDomEl;
openedWindows.top().value.modalOpener = modalOpener;

$modalStack.clearFocusListCache();
};

Expand Down
96 changes: 76 additions & 20 deletions src/modal/test/modal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,23 @@ describe('$uibModal', function () {
beforeEach(module('ui.bootstrap.modal'));
beforeEach(module('uib/template/modal/backdrop.html'));
beforeEach(module('uib/template/modal/window.html'));
beforeEach(module(function(_$controllerProvider_, _$uibModalProvider_){
beforeEach(module(function(_$controllerProvider_, _$uibModalProvider_, $compileProvider) {
$controllerProvider = _$controllerProvider_;
$uibModalProvider = _$uibModalProvider_;
$compileProvider.directive('parentDirective', function() {
return {
controller: function() {
this.text = 'foo';
}
};
}).directive('childDirective', function() {
return {
require: '^parentDirective',
link: function(scope, elem, attrs, ctrl) {
scope.text = ctrl.text;
}
};
});
}));

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

function open(modalOptions) {
function open(modalOptions, noFlush) {
var modal = $uibModal.open(modalOptions);
$rootScope.$digest();
$timeout.flush(0);
if (!noFlush) {
$animate.flush();
}
return modal;
}

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

it('should expose a promise linked to the templateUrl / resolve promises and reject it if needed', function() {
var modal = open({template: '<div>Content</div>', resolve: {
ok: function() {return $q.reject('ko');}
}}
);
ok: function() {return $q.reject('ko');}
}}, true);
expect(modal.opened).toBeRejectedWith('ko');
});

Expand Down Expand Up @@ -633,10 +648,11 @@ describe('$uibModal', function () {
value: function() {
return $timeout(function() { return 'Promise'; }, 100);
}
}));
}), true);
expect($document).toHaveModalsOpen(0);

$timeout.flush();
$animate.flush();
expect($document).toHaveModalOpenWithContent('Promise', 'div');
});

Expand All @@ -647,7 +663,7 @@ describe('$uibModal', function () {
value: function() {
return deferred.promise;
}
}));
}), true);
expect($document).toHaveModalsOpen(0);

deferred.reject('error in test');
Expand Down Expand Up @@ -858,6 +874,8 @@ describe('$uibModal', function () {
expect($document.find('section').children('div.modal').length).toBe(0);
open({template: '<div>Content</div>', appendTo: element});
expect($document.find('section').children('div.modal').length).toBe(1);

element.remove();
});

it('should throw error if appendTo element is not found', function() {
Expand All @@ -874,6 +892,17 @@ describe('$uibModal', function () {
dismiss(modal);
expect($document).toHaveModalsOpen(0);
});

it('should allow requiring parent directive from appendTo target', function() {
var element = $compile('<section parent-directive>Some content</section>')($rootScope);
angular.element(document.body).append(element);

open({template: '<div child-directive>{{text}}</div>', appendTo: element});
$animate.flush();
expect($document.find('[child-directive]').text()).toBe('foo');

element.remove();
});
});

describe('openedClass', function() {
Expand Down Expand Up @@ -1008,7 +1037,7 @@ describe('$uibModal', function () {
expect($document).toHaveModalsOpen(2);
});

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

var scope = $rootScope.$new();
scope.index = i;
Expand All @@ -1094,17 +1123,17 @@ describe('$uibModal', function () {
resolve: {
x: function() { return ds[x].deferred.promise; }
}
}).opened.then(function() {
}, true).opened.then(function() {
expect($uibModalStack.getTop().value.modalScope.index).toEqual(i);
actual += i;
});
});

angular.forEach(ds, function(d, i) {
if (d.reject) {
d.deferred.reject('rejected:' + d.index );
d.deferred.reject('rejected:' + d.index);
} else {
d.deferred.resolve('resolved:' + d.index );
d.deferred.resolve('resolved:' + d.index);
}
$rootScope.$digest();
});
Expand Down Expand Up @@ -1138,13 +1167,39 @@ describe('$uibModal', function () {
_permute(0);
}

permute(2, function(a) { test(a); });
permute(2, function(a) { test(a.map(function(x, i) { return {reject:x}; })); });
permute(2, function(a) { test(a.map(function(x, i) { return i === 0 ? {reject:x} : x; })); });
permute(3, function(a) { test(a); });
permute(3, function(a) { test(a.map(function(x, i) { return {reject:x}; })); });
permute(3, function(a) { test(a.map(function(x, i) { return i === 0 ? {reject:x} : x; })); });
permute(3, function(a) { test(a.map(function(x, i) { return i === 1 ? {reject:x} : x; })); });
permute(2, function(a) {
test(a);
});
permute(2, function(a) {
test(a.map(function(x, i) {
return {reject:x};
}));
});
permute(2, function(a) {
test(a.map(function(x, i) {
return i === 0 ? {reject: x} : x;
}));
});
permute(3, function(a) {
test(a);
});
permute(3, function(a) {
test(a.map(function(x, i) {
return {reject: x};
}));
});
permute(3, function(a) {
test(a.map(function(x, i) {
return i === 0 ? {reject: x} : x;
}));
});
permute(3, function(a) {
test(a.map(function(x, i) {
return i === 1 ? {reject: x} : x;
}));
});

$animate.flush();
});

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

called = false;

close(open({
template: '<div>content</div>',
controller: function($scope) {
Expand Down

0 comments on commit e28cced

Please sign in to comment.