Skip to content
This repository was archived by the owner on Dec 1, 2023. It is now read-only.

Commit 4b80b37

Browse files
committed
fix(modal): use safe $digest calls to ease controller usage
1 parent f8a92d8 commit 4b80b37

2 files changed

Lines changed: 53 additions & 13 deletions

File tree

src/modal/modal.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,18 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
9494
if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html="');
9595
template = trim.apply(template);
9696
modalLinker = $compile(template);
97-
// modalElement = modalLinker(scope);
9897
$modal.init();
9998
});
10099

101100
$modal.init = function() {
101+
102+
// Options: show
102103
if(options.show) {
103104
scope.$$postDigest(function() {
104105
$modal.show();
105106
});
106107
}
108+
107109
};
108110

109111
$modal.destroy = function() {
@@ -120,6 +122,7 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
120122

121123
// Destroy scope
122124
scope.$destroy();
125+
123126
};
124127

125128
$modal.show = function() {
@@ -146,7 +149,7 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
146149
}
147150
$animate.enter(modalElement, parent, after, function() {});
148151
scope.$isShown = true;
149-
scope.$digest();
152+
scope.$$phase || scope.$digest();
150153
$modal.focus();
151154

152155
bodyElement.addClass(options.prefixClass + '-open');
@@ -175,7 +178,7 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
175178
if(options.backdrop) {
176179
$animate.leave(backdropElement, function() {});
177180
}
178-
scope.$digest();
181+
scope.$$phase || scope.$digest();
179182
scope.$isShown = false;
180183

181184
// Unbind events

src/modal/test/modal.spec.js

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
'use strict';
22

3-
describe('modal', function () {
3+
describe('modal', function() {
44

5-
var $compile, $templateCache, scope, sandboxEl;
5+
var bodyEl = $('body'), sandboxEl;
6+
var $compile, $templateCache, $modal, scope;
67

78
beforeEach(module('ngSanitize'));
89
beforeEach(module('mgcrea.ngStrap.modal'));
910

10-
beforeEach(inject(function (_$rootScope_, _$compile_, _$templateCache_) {
11+
beforeEach(inject(function (_$rootScope_, _$compile_, _$templateCache_, _$modal_) {
1112
scope = _$rootScope_.$new();
12-
sandboxEl = $('<div>').attr('id', 'sandbox').appendTo($('body'));
13+
bodyEl.html('');
14+
sandboxEl = $('<div>').attr('id', 'sandbox').appendTo(bodyEl);
1315
$compile = _$compile_;
1416
$templateCache = _$templateCache_;
17+
$modal = _$modal_;
1518
}));
1619

1720
afterEach(function() {
@@ -33,6 +36,9 @@ describe('modal', function () {
3336
scope: {items: [{name: 'foo', modal: {title: 'Title', content: 'Hello Modal!'}}]},
3437
element: '<ul><li ng-repeat="item in items"><a title="{{item.modal.title}}" data-content="{{item.modal.content}}" bs-modal>{{item.name}}</a></li></ul>'
3538
},
39+
'markup-ngClick-service': {
40+
element: '<a ng-click="showModal()">click me</a>'
41+
},
3642
'options-placement': {
3743
element: '<a data-placement="bottom" bs-modal="modal">click me</a>'
3844
},
@@ -60,7 +66,7 @@ describe('modal', function () {
6066

6167
// Tests
6268

63-
describe('with default template', function () {
69+
describe('with default template', function() {
6470

6571
it('should open on click', function() {
6672
var elm = compileDirective('default');
@@ -100,10 +106,41 @@ describe('modal', function () {
100106

101107
});
102108

109+
describe('using service', function() {
110+
111+
it('should correctly open on next digest', function() {
112+
var myModal = $modal(templates['default'].scope.modal);
113+
scope.$digest();
114+
expect(bodyEl.children('.modal').length).toBe(1);
115+
myModal.hide();
116+
expect(bodyEl.children('.modal').length).toBe(0);
117+
});
118+
119+
it('should correctly be destroyed', function() {
120+
var myModal = $modal(angular.extend(templates['default'].scope.modal));
121+
scope.$digest();
122+
expect(bodyEl.children('.modal').length).toBe(1);
123+
myModal.destroy();
124+
expect(bodyEl.children('.modal').length).toBe(0);
125+
expect(bodyEl.children().length).toBe(1);
126+
});
127+
128+
it('should correctly work with ngClick', function() {
129+
var elm = compileDirective('markup-ngClick-service');
130+
var myModal = $modal(angular.extend({show: false}, templates['default'].scope.modal));
131+
scope.showModal = function() {
132+
myModal.$promise.then(myModal.show);
133+
};
134+
expect(bodyEl.children('.modal').length).toBe(0);
135+
angular.element(elm[0]).triggerHandler('click');
136+
expect(bodyEl.children('.modal').length).toBe(1);
137+
});
138+
139+
});
103140

104-
describe('options', function () {
141+
describe('options', function() {
105142

106-
describe('animation', function () {
143+
describe('animation', function() {
107144

108145
it('should default to `animation-fade` animation', function() {
109146
var elm = compileDirective('default');
@@ -113,7 +150,7 @@ describe('modal', function () {
113150

114151
});
115152

116-
describe('placement', function () {
153+
describe('placement', function() {
117154

118155
it('should default to `top` placement', function() {
119156
var elm = compileDirective('default');
@@ -135,7 +172,7 @@ describe('modal', function () {
135172

136173
});
137174

138-
describe('html', function () {
175+
describe('html', function() {
139176

140177
it('should correctly compile inner content', function() {
141178
var elm = compileDirective('options-html');
@@ -146,7 +183,7 @@ describe('modal', function () {
146183

147184
});
148185

149-
describe('template', function () {
186+
describe('template', function() {
150187

151188
it('should support custom template', function() {
152189
$templateCache.put('custom', '<div class="modal"><div class="modal-inner">foo: {{title}}</div></div>');

0 commit comments

Comments
 (0)