@@ -1480,6 +1480,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
1480
1480
} ) ;
1481
1481
} ;
1482
1482
1483
+ // We need to attach the transclusion slots onto the `boundTranscludeFn`
1484
+ // so that they are available inside the `controllersBoundTransclude` function
1485
+ var boundSlots = boundTranscludeFn . $$slots = createMap ( ) ;
1486
+ for ( var slotName in transcludeFn . $$slots ) {
1487
+ boundSlots [ slotName ] = createBoundTranscludeFn ( scope , transcludeFn . $$slots [ slotName ] , previousBoundTranscludeFn ) ;
1488
+ }
1489
+
1483
1490
return boundTranscludeFn ;
1484
1491
}
1485
1492
@@ -1821,9 +1828,56 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
1821
1828
nonTlbTranscludeDirective : nonTlbTranscludeDirective
1822
1829
} ) ;
1823
1830
} else {
1831
+
1832
+ var slots = createMap ( ) ;
1824
1833
$template = jqLite ( jqLiteClone ( compileNode ) ) . contents ( ) ;
1834
+
1835
+ if ( isObject ( directiveValue ) ) {
1836
+
1837
+ // We have transclusion slots - collect them up and compile them and store their
1838
+ // transclusion functions
1839
+ $template = [ ] ;
1840
+ var slotNames = createMap ( ) ;
1841
+ var filledSlots = createMap ( ) ;
1842
+
1843
+ // Parse the slot names: if they start with a ? then they are optional
1844
+ forEach ( directiveValue , function ( slotName , key ) {
1845
+ var optional = ( slotName . charAt ( 0 ) === '?' ) ;
1846
+ slotName = optional ? slotName . substring ( 1 ) : slotName ;
1847
+ slotNames [ key ] = slotName ;
1848
+ slots [ slotName ] = [ ] ;
1849
+ // filledSlots contains `true` for all slots that are either optional or have been
1850
+ // filled. This is used to check that we have not missed any required slots
1851
+ filledSlots [ slotName ] = optional ;
1852
+ } ) ;
1853
+
1854
+ // Add the matching elements into their slot
1855
+ forEach ( $compileNode . children ( ) , function ( node ) {
1856
+ var slotName = slotNames [ directiveNormalize ( nodeName_ ( node ) ) ] ;
1857
+ var slot = $template ;
1858
+ if ( slotName ) {
1859
+ filledSlots [ slotName ] = true ;
1860
+ slots [ slotName ] . push ( node ) ;
1861
+ } else {
1862
+ $template . push ( node ) ;
1863
+ }
1864
+ } ) ;
1865
+
1866
+ // Check for required slots that were not filled
1867
+ forEach ( filledSlots , function ( filled , slotName ) {
1868
+ if ( ! filled ) {
1869
+ throw $compileMinErr ( 'reqslot' , 'Required transclusion slot `{0}` was not filled.' , slotName ) ;
1870
+ }
1871
+ } ) ;
1872
+
1873
+ forEach ( Object . keys ( slots ) , function ( slotName ) {
1874
+ slots [ slotName ] = compilationGenerator ( mightHaveMultipleTransclusionError , slots [ slotName ] , transcludeFn ) ;
1875
+ } ) ;
1876
+ }
1877
+
1825
1878
$compileNode . empty ( ) ; // clear contents
1826
1879
childTranscludeFn = compilationGenerator ( mightHaveMultipleTransclusionError , $template , transcludeFn ) ;
1880
+ childTranscludeFn . $$slots = slots ;
1827
1881
}
1828
1882
}
1829
1883
@@ -2130,11 +2184,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
2130
2184
2131
2185
// This is the function that is injected as `$transclude`.
2132
2186
// Note: all arguments are optional!
2133
- function controllersBoundTransclude ( scope , cloneAttachFn , futureParentElement ) {
2187
+ function controllersBoundTransclude ( scope , cloneAttachFn , futureParentElement , slotName ) {
2134
2188
var transcludeControllers ;
2135
-
2136
2189
// No scope passed in:
2137
2190
if ( ! isScope ( scope ) ) {
2191
+ slotName = futureParentElement ;
2138
2192
futureParentElement = cloneAttachFn ;
2139
2193
cloneAttachFn = scope ;
2140
2194
scope = undefined ;
@@ -2146,6 +2200,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
2146
2200
if ( ! futureParentElement ) {
2147
2201
futureParentElement = hasElementTranscludeDirective ? $element . parent ( ) : $element ;
2148
2202
}
2203
+ if ( slotName ) {
2204
+ var slotTranscludeFn = boundTranscludeFn . $$slots [ slotName ] ;
2205
+ if ( ! slotTranscludeFn ) {
2206
+ throw $compileMinErr ( 'noslot' ,
2207
+ 'No parent directive that requires a transclusion with slot name "{0}". ' +
2208
+ 'Element: {1}' ,
2209
+ slotName , startingTag ( $element ) ) ;
2210
+ }
2211
+ return slotTranscludeFn ( scope , cloneAttachFn , transcludeControllers , futureParentElement , scopeToChild ) ;
2212
+ }
2149
2213
return boundTranscludeFn ( scope , cloneAttachFn , transcludeControllers , futureParentElement , scopeToChild ) ;
2150
2214
}
2151
2215
}
0 commit comments