Skip to content

Commit aad6b01

Browse files
petebacondarwinCameron Knight
authored and
Cameron Knight
committed
docs(guide/unit-testing): add info on testing element transclude directives
Closes angular#4505 Closes angular#8197
1 parent 2f88f22 commit aad6b01

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

docs/content/guide/unit-testing.ngdoc

+74
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,80 @@ We inject the $compile service and $rootScope before each jasmine test. The $com
337337
to render the aGreatEye directive. After rendering the directive we ensure that the directive has
338338
replaced the content and "lidless, wreathed in flame, 2 times" is present.
339339

340+
### Testing Transclusion Directives
341+
342+
Directives that use transclusion are treated specially by the compiler. Before their compile
343+
function is called, the contents of the directive's element are removed from the element and
344+
provided via a transclusion function. The directive's template is then appended to the directive's
345+
element, to which it can then insert the transcluded content into its template.
346+
347+
348+
Before compilation:
349+
```html
350+
<div translude-directive>
351+
Some transcluded content
352+
</div>
353+
```
354+
355+
After transclusion extraction:
356+
```html
357+
<div transclude-directive></div>
358+
```
359+
360+
After compilation:
361+
```html
362+
<div transclude-directive>
363+
Some Template
364+
<span ng-transclude>Some transcluded content</span>
365+
</div>
366+
```
367+
368+
If the directive is using 'element' transclusion, the compiler will actually remove the
369+
directive's entire element from the DOM and replace it with a comment node. The compiler then
370+
inserts the directive's template "after" this comment node, as a sibling.
371+
372+
Before compilation
373+
```html
374+
<div element-transclude>
375+
Some Content
376+
</div>
377+
```
378+
379+
After transclusion extraction
380+
```html
381+
<!-- elementTransclude -->
382+
```
383+
384+
After compilation:
385+
```html
386+
<!-- elementTransclude -->
387+
<div element-transclude>
388+
Some Template
389+
<span ng-transclude>Some transcluded content</span>
390+
</div>
391+
```
392+
393+
It is important to be aware of this when writing tests for directives that use 'element'
394+
transclusion. If you place the directive on the root element of the DOM fragment that you
395+
pass to {@link $compile}, then the DOM node returned from the linking function will be the
396+
comment node and you will lose the ability to access the template and transcluded content.
397+
398+
```javascript
399+
var node = $compile('<div element-transclude></div>')($rootScope);
400+
expect(node[0].nodeType).toEqual(node.COMMENT_NODE);
401+
expect(node[1]).toBeUndefined();
402+
```
403+
404+
To cope with this you simply ensure that your 'element' transclude directive is wrapped in an
405+
element, such as a `<div>`.
406+
407+
```javascript
408+
var node = $compile('<div><div element-transclude></div></div>')($rootScope);
409+
var contents = node.contents();
410+
expect(contents[0].nodeType).toEqual(node.COMMENT_NODE);
411+
expect(contents[1].nodeType).toEqual(node.ELEMENT_NODE);
412+
```
413+
340414
### Testing Directives With External Templates
341415

342416
If your directive uses `templateUrl`, consider using

src/ng/compile.js

+5
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,11 @@
266266
* * `true` - transclude the content of the directive.
267267
* * `'element'` - transclude the whole element including any directives defined at lower priority.
268268
*
269+
* <div class="alert alert-warning">
270+
* **Note:** When testing an element transclude directive you must not place the directive at the root of the
271+
* DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives
272+
* Testing Transclusion Directives}.
273+
* </div>
269274
*
270275
* #### `compile`
271276
*

0 commit comments

Comments
 (0)