From def1619bed6858cc7c869c9fde4a4255086b6fe8 Mon Sep 17 00:00:00 2001 From: Kara Erickson Date: Tue, 2 Jun 2015 10:32:18 -0700 Subject: [PATCH] feat(ngTranscludeSelect): add ng-transclude-select directive The ng-translude-select directive allows users to transclude multiple templates into their directive. --- angularFiles.js | 1 + src/AngularPublic.js | 2 + src/ng/directive/ngTranscludeSelect.js | 49 +++++++++++++++++++++ test/ng/directive/ngTranscludeSelectSpec.js | 37 ++++++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 src/ng/directive/ngTranscludeSelect.js create mode 100644 test/ng/directive/ngTranscludeSelectSpec.js diff --git a/angularFiles.js b/angularFiles.js index 702d5efd6290..d64016742e67 100755 --- a/angularFiles.js +++ b/angularFiles.js @@ -73,6 +73,7 @@ var angularFiles = { 'src/ng/directive/ngStyle.js', 'src/ng/directive/ngSwitch.js', 'src/ng/directive/ngTransclude.js', + 'src/ng/directive/ngTranscludeSelect.js', 'src/ng/directive/script.js', 'src/ng/directive/select.js', 'src/ng/directive/style.js', diff --git a/src/AngularPublic.js b/src/AngularPublic.js index 3f530626d3e2..e0721a209b68 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -39,6 +39,7 @@ ngSwitchDefaultDirective, ngOptionsDirective, ngTranscludeDirective, + ngTranscludeSelectDirective, ngModelDirective, ngListDirective, ngChangeDirective, @@ -197,6 +198,7 @@ function publishExternalAPI(angular) { ngSwitchDefault: ngSwitchDefaultDirective, ngOptions: ngOptionsDirective, ngTransclude: ngTranscludeDirective, + ngTranscludeSelect: ngTranscludeSelectDirective, ngModel: ngModelDirective, ngList: ngListDirective, ngChange: ngChangeDirective, diff --git a/src/ng/directive/ngTranscludeSelect.js b/src/ng/directive/ngTranscludeSelect.js new file mode 100644 index 000000000000..89dfe3ebcc21 --- /dev/null +++ b/src/ng/directive/ngTranscludeSelect.js @@ -0,0 +1,49 @@ +'use strict'; + +/** + * @ngdoc directive + * @name ngTranscludeSelect + * @restrict EAC + * + * @description + * + * @element ANY + * + */ +var ngTranscludeSelectDirective = ngDirective({ + restrict: 'EAC', + link: function($scope, $element, $attrs, controller, $transclude) { + checkTranscludeOption(); + $transclude(transcludeSelection); + + function transcludeSelection(clone) { + var selector = $attrs.ngTranscludeSelect; + var selectedElements = getSelectedElements(clone, selector); + if (selectedElements.length) $element.append(selectedElements); + } + + function getSelectedElements(clone, selector) { + var wrapper = wrapClone(clone); + var selectedElements = wrapper[0].querySelectorAll(selector); + wrapper.remove(); + return selectedElements; + } + + function wrapClone(clone) { + var wrapper = jqLite("
"); + wrapper.append(clone); + return wrapper; + } + + function checkTranscludeOption() { + if (!$transclude) { + throw minErr('ngTransclude')('orphan', + 'Illegal use of ngTranscludeSelect directive in the template! ' + + 'No parent directive that requires a transclusion found. ' + + 'Element: {0}', + startingTag($element)); + } + } + } +}); + diff --git a/test/ng/directive/ngTranscludeSelectSpec.js b/test/ng/directive/ngTranscludeSelectSpec.js new file mode 100644 index 000000000000..6f932b14848e --- /dev/null +++ b/test/ng/directive/ngTranscludeSelectSpec.js @@ -0,0 +1,37 @@ +'use strict'; + + +describe('ngTranscludeSelect', function() { + it('should append matching clone elements to ng-transclude-select elements', function() { + module(function($compileProvider) { + $compileProvider.directive('transclude', valueFn({ + transclude: true, + scope: {}, + template: '
' + })); + }); + inject(function($compile, $rootScope) { + var topTarget, bottomTarget; + var element = $compile( + '
In bottom.
In top.
' + )($rootScope); + topTarget = jqLite(element[0].querySelector('[ng-transclude-select="[top]"]')); + bottomTarget = jqLite(element[0].querySelector('[ng-transclude-select="[bottom]"]')); + expect(topTarget.text()).toEqual('In top.'); + expect(bottomTarget.text()).toEqual('In bottom.'); + }); + }); + it('should throw on an ng-transclude-select element inside no transclusion directive', function() { + inject(function($rootScope, $compile) { + try { + $compile('
')($rootScope); + } catch (e) { + expect(e.message).toMatch(new RegExp( + '^\\[ngTransclude:orphan\\] ' + + 'Illegal use of ngTranscludeSelect directive in the template! ' + + 'No parent directive that requires a transclusion found\\. ' + + 'Element: