From 0db7684ffead8990fcd0cbef635b4a326e3c10aa Mon Sep 17 00:00:00 2001 From: Topher Fangio Date: Sun, 18 Oct 2015 07:10:26 -0500 Subject: [PATCH] fix(dialog): Provide option to not autowrap templates. For convenience, we automatically wrap templates that do not contain a `` tag within them. However, some users would like the ability to create their own dialog directives (like ``) that internally use the `` tag within their template. This causes two `` tags to be created. Provide a new `autoWrap` option which can be set to false to disable autowrapping when providing a custom directive. Fixes #4898. --- src/components/dialog/dialog.js | 15 +++-- src/components/dialog/dialog.spec.js | 68 ++++++++++++++------- src/core/services/compiler/compiler.js | 2 +- src/core/services/compiler/compiler.spec.js | 9 +++ 4 files changed, 67 insertions(+), 27 deletions(-) diff --git a/src/components/dialog/dialog.js b/src/components/dialog/dialog.js index 18aabf8e93e..e5fad9f2426 100644 --- a/src/components/dialog/dialog.js +++ b/src/components/dialog/dialog.js @@ -333,6 +333,9 @@ function MdDialogDirective($$rAF, $mdTheming, $mdDialog) { * - `templateUrl` - `{string=}`: The url of a template that will be used as the content * of the dialog. * - `template` - `{string=}`: Same as templateUrl, except this is an actual template string. + * - `autoWrap` - `{boolean=}`: Whether or not to automatically wrap the template with a + * `` tag if one is not provided. Defaults to true. Can be disabled if you provide a + * custom dialog directive. * - `targetEvent` - `{DOMClickEvent=}`: A click's event object. When passed in as an option, * the location of the click will be used as the starting point for the opening animation * of the the dialog. @@ -374,7 +377,7 @@ function MdDialogDirective($$rAF, $mdTheming, $mdDialog) { * starting. * - `onComplete` `{function=}`: Callback function used to announce when the show() action is * finished. - * - `onRemoving` `{function=} Callback function used to announce the close/hide() action is + * - `onRemoving` `{function=}`: Callback function used to announce the close/hide() action is * starting. This allows developers to run custom animations in parallel the close animations. * * @returns {promise} A promise that can be resolved with `$mdDialog.hide()` or @@ -469,15 +472,19 @@ function MdDialogProvider($$interimElementProvider) { openFrom: null, focusOnOpen: true, disableParentScroll: true, - transformTemplate: function(template) { + autoWrap: true, + transformTemplate: function(template, options) { return '
' + validatedTemplate(template) + '
'; /** * The specified template should contain a wrapper element.... */ function validatedTemplate(template) { - template || "" - return /<\/md-dialog>/g.test(template) ? template : "" + template + ""; + if (options.autoWrap && !/<\/md-dialog>/g.test(template)) { + return '' + (template || '') + ''; + } else { + return template || ''; + } } } }; diff --git a/src/components/dialog/dialog.spec.js b/src/components/dialog/dialog.spec.js index 5a25f413986..e8cd7b66066 100644 --- a/src/components/dialog/dialog.spec.js +++ b/src/components/dialog/dialog.spec.js @@ -545,37 +545,61 @@ describe('$mdDialog', function() { nodes.remove(); })); - it('should not wrap content with existing md-dialog', inject(function($mdDialog, $rootScope) { + describe('when autoWrap parameter is true (default)', function() { - var template = '
Hello
'; - var parent = angular.element('
'); + it('should not wrap content with existing md-dialog', inject(function($mdDialog, $rootScope) { - $mdDialog.show({ - template: template, - parent: parent - }); + var template = '
Hello
'; + var parent = angular.element('
'); - $rootScope.$apply(); + $mdDialog.show({ + template: template, + parent: parent + }); - var container = parent[0].querySelectorAll('md-dialog'); - expect(container.length).toBe(1); - })); + $rootScope.$apply(); - it('should wrap raw content with md-dialog', inject(function($mdDialog, $rootScope) { + var container = parent[0].querySelectorAll('md-dialog'); + expect(container.length).toBe(1); + })); - var template = '
Hello
'; - var parent = angular.element('
'); + it('should wrap raw content with md-dialog', inject(function($mdDialog, $rootScope) { - $mdDialog.show({ - template: template, - parent: parent - }); + var template = '
Hello
'; + var parent = angular.element('
'); - $rootScope.$apply(); + $mdDialog.show({ + template: template, + parent: parent + }); - var container = parent[0].querySelectorAll('md-dialog'); - expect(container.length).toBe(1); - })); + $rootScope.$apply(); + + var container = parent[0].querySelectorAll('md-dialog'); + expect(container.length).toBe(1); + })); + }); + + + describe('when autoWrap parameter is false', function() { + + it('should not wrap raw content with md-dialog', inject(function($mdDialog, $rootScope) { + + var template = '
Hello
'; + var parent = angular.element('
'); + + $mdDialog.show({ + template: template, + parent: parent, + autoWrap: false + }); + + $rootScope.$apply(); + + var container = parent[0].querySelectorAll('md-dialog'); + expect(container.length).toBe(0); + })); + }); it('should append dialog within a md-dialog-container', inject(function($mdDialog, $rootScope) { diff --git a/src/core/services/compiler/compiler.js b/src/core/services/compiler/compiler.js index 291f8351304..85fa76cbe25 100644 --- a/src/core/services/compiler/compiler.js +++ b/src/core/services/compiler/compiler.js @@ -101,7 +101,7 @@ function mdCompilerService($q, $http, $injector, $compile, $controller, $templat return $q.all(resolve).then(function(locals) { var compiledData; - var template = transformTemplate(locals.$template); + var template = transformTemplate(locals.$template, options); var element = options.element || angular.element('
').html(template.trim()).contents(); var linkFn = $compile(element); diff --git a/src/core/services/compiler/compiler.spec.js b/src/core/services/compiler/compiler.spec.js index e5627f2edd7..bf8d956f1bb 100644 --- a/src/core/services/compiler/compiler.spec.js +++ b/src/core/services/compiler/compiler.spec.js @@ -54,6 +54,15 @@ describe('$mdCompiler service', function() { expect(data.element.html()).toBe('hello world'); }); + it('transformTemplate receives the options', function() { + var data = compile({ + template: 'world', + someArg: 'foo', + transformTemplate: function(tpl, options) { return 'hello ' + tpl + ': ' + options.someArg; } + }); + expect(data.element.html()).toBe('hello world: foo'); + }); + describe('with resolve and locals options', function() { var options;