Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

feat(ngTranscludeSelect): add ng-transclude-select directive for multi-transclusion #11736

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions angularFiles.js
Expand Up @@ -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',
Expand Down
2 changes: 2 additions & 0 deletions src/AngularPublic.js
Expand Up @@ -39,6 +39,7 @@
ngSwitchDefaultDirective,
ngOptionsDirective,
ngTranscludeDirective,
ngTranscludeSelectDirective,
ngModelDirective,
ngListDirective,
ngChangeDirective,
Expand Down Expand Up @@ -197,6 +198,7 @@ function publishExternalAPI(angular) {
ngSwitchDefault: ngSwitchDefaultDirective,
ngOptions: ngOptionsDirective,
ngTransclude: ngTranscludeDirective,
ngTranscludeSelect: ngTranscludeSelectDirective,
ngModel: ngModelDirective,
ngList: ngListDirective,
ngChange: ngChangeDirective,
Expand Down
49 changes: 49 additions & 0 deletions 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("<div>");
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));
}
}
}
});

37 changes: 37 additions & 0 deletions 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: '<div ng-transclude-select="[top]"></div><div ng-transclude-select="[bottom]"></div>'
}));
});
inject(function($compile, $rootScope) {
var topTarget, bottomTarget;
var element = $compile(
'<div transclude><div bottom>In bottom.</div><div top>In top.</div></div></div>'
)($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('<div><div ng-transclude-select="[top]"></div></div>')($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: <div ng-transclude-select.+'));
}
});
});
});