@@ -266,6 +266,7 @@ export class BehaviorInstruction {
266
266
instruction . host = host ;
267
267
instruction . viewModel = viewModel ;
268
268
instruction . viewFactory = viewFactory ;
269
+ instruction . inheritBindingContext = true ;
269
270
return instruction ;
270
271
}
271
272
@@ -286,6 +287,7 @@ export class BehaviorInstruction {
286
287
this . attributes = null ;
287
288
this . type = null ;
288
289
this . attrName = null ;
290
+ this . inheritBindingContext = false ;
289
291
}
290
292
}
291
293
@@ -2086,7 +2088,7 @@ export class BoundViewFactory {
2086
2088
constructor ( parentContainer : Container , viewFactory : ViewFactory , partReplacements ? : Object ) {
2087
2089
this . parentContainer = parentContainer ;
2088
2090
this . viewFactory = viewFactory ;
2089
- this . factoryCreateInstruction = { partReplacements : partReplacements } ;
2091
+ this . factoryCreateInstruction = { partReplacements : partReplacements } ; //This is referenced internally in the controller's bind method.
2090
2092
}
2091
2093
2092
2094
/**
@@ -3226,7 +3228,7 @@ export class Controller {
3226
3228
this . isAttached = false ;
3227
3229
this . view = null ;
3228
3230
this . isBound = false ;
3229
- this . bindingContext = null ;
3231
+ this . scope = null ;
3230
3232
3231
3233
let observerLookup = behavior . observerLocator . getOrCreateObserversLookup ( viewModel ) ;
3232
3234
let handlesBind = behavior . handlesBind ;
@@ -3264,7 +3266,7 @@ export class Controller {
3264
3266
this . view . overrideContext = overrideContext || createOverrideContext ( this . viewModel ) ;
3265
3267
this . view . _isUserControlled = true ;
3266
3268
3267
- if ( this . behavior . handlesCreated ) {
3269
+ if ( this . behavior . handlesCreated ) {
3268
3270
this . viewModel . created ( owningView || null , this . view ) ;
3269
3271
}
3270
3272
@@ -3283,18 +3285,17 @@ export class Controller {
3283
3285
let x ;
3284
3286
let observer ;
3285
3287
let selfSubscriber ;
3286
- let context = scope . bindingContext ;
3287
3288
3288
3289
if ( this . isBound ) {
3289
- if ( this . bindingContext === context ) {
3290
+ if ( this . scope === scope ) {
3290
3291
return ;
3291
3292
}
3292
3293
3293
3294
this . unbind ( ) ;
3294
3295
}
3295
3296
3296
3297
this . isBound = true ;
3297
- this . bindingContext = context ;
3298
+ this . scope = scope ;
3298
3299
3299
3300
for ( i = 0 , ii = boundProperties . length ; i < ii ; ++ i ) {
3300
3301
x = boundProperties [ i ] ;
@@ -3313,14 +3314,40 @@ export class Controller {
3313
3314
observer . selfSubscriber = selfSubscriber ;
3314
3315
}
3315
3316
3317
+ let overrideContext ;
3316
3318
if ( this . view !== null ) {
3317
3319
if ( skipSelfSubscriber ) {
3318
3320
this . view . viewModelScope = scope ;
3319
3321
}
3320
-
3321
- this . view . bind ( this . viewModel , createOverrideContext ( this . viewModel , scope . overrideContext ) ) ;
3322
+ // do we need to create an overrideContext or is the scope's overrideContext
3323
+ // valid for this viewModel?
3324
+ if ( this . viewModel === scope . overrideContext . bindingContext ) {
3325
+ overrideContext = scope . overrideContext ;
3326
+ // should we inherit the parent scope? (eg compose / router)
3327
+ } else if ( this . instruction . inheritBindingContext ) {
3328
+ overrideContext = createOverrideContext ( this . viewModel , scope . overrideContext ) ;
3329
+ // create the overrideContext and capture the parent without making it
3330
+ // available to AccessScope. We may need it later for template-part replacements.
3331
+ } else {
3332
+ overrideContext = createOverrideContext ( this . viewModel ) ;
3333
+ overrideContext . __parentOverrideContext = scope . overrideContext ;
3334
+ }
3335
+ this . view . bind ( this . viewModel , overrideContext ) ;
3322
3336
} else if ( skipSelfSubscriber ) {
3323
- this . viewModel . bind ( context , scope . overrideContext ) ;
3337
+ overrideContext = scope . overrideContext ;
3338
+ // the factoryCreateInstruction's partReplacements will either be null or an object
3339
+ // containing the replacements. If there are partReplacements we need to preserve the parent
3340
+ // context to allow replacement parts to bind to both the custom element scope and the ambient scope.
3341
+ // Note that factoryCreateInstruction is a property defined on BoundViewFactory. The code below assumes the
3342
+ // behavior stores a the BoundViewFactory on its viewModel under the name of viewFactory. This is implemented
3343
+ // by the replaceable custom attribute.
3344
+ if ( scope . overrideContext . __parentOverrideContext !== undefined
3345
+ && this . viewModel . viewFactory && this . viewModel . viewFactory . factoryCreateInstruction . partReplacements ) {
3346
+ // clone the overrideContext and connect the ambient context.
3347
+ overrideContext = Object . assign ( { } , scope . overrideContext ) ;
3348
+ overrideContext . parentOverrideContext = scope . overrideContext . __parentOverrideContext ;
3349
+ }
3350
+ this . viewModel . bind ( scope . bindingContext , overrideContext ) ;
3324
3351
}
3325
3352
}
3326
3353
@@ -3932,7 +3959,7 @@ export class HtmlBehaviorResource {
3932
3959
node = template ;
3933
3960
}
3934
3961
} else if ( this . elementName !== null ) { //custom element
3935
- let partReplacements = instruction . partReplacements = { } ;
3962
+ let partReplacements = { } ;
3936
3963
3937
3964
if ( this . processContent ( compiler , resources , node , instruction ) && node . hasChildNodes ( ) ) {
3938
3965
if ( this . usesShadowDOM ) {
@@ -3946,6 +3973,7 @@ export class HtmlBehaviorResource {
3946
3973
if ( currentChild . tagName === 'TEMPLATE' && ( toReplace = currentChild . getAttribute ( 'replace-part' ) ) ) {
3947
3974
partReplacements [ toReplace ] = compiler . compile ( currentChild , resources ) ;
3948
3975
DOM . removeNode ( currentChild , parentNode ) ;
3976
+ instruction . partReplacements = partReplacements ;
3949
3977
}
3950
3978
3951
3979
currentChild = nextSibling ;
@@ -3964,6 +3992,7 @@ export class HtmlBehaviorResource {
3964
3992
if ( currentChild . tagName === 'TEMPLATE' && ( toReplace = currentChild . getAttribute ( 'replace-part' ) ) ) {
3965
3993
partReplacements [ toReplace ] = compiler . compile ( currentChild , resources ) ;
3966
3994
DOM . removeNode ( currentChild , parentNode ) ;
3995
+ instruction . partReplacements = partReplacements ;
3967
3996
} else {
3968
3997
fragment . appendChild ( currentChild ) ;
3969
3998
}
@@ -4144,14 +4173,14 @@ function createChildObserverDecorator(selectorOrConfig, all) {
4144
4173
}
4145
4174
4146
4175
/**
4147
- * Creates a behavior property that references an array of immediate content child elememnts that matches the provided selector.
4176
+ * Creates a behavior property that references an array of immediate content child elements that matches the provided selector.
4148
4177
*/
4149
4178
export function children ( selectorOrConfig : string | Object ) : any {
4150
4179
return createChildObserverDecorator ( selectorOrConfig , true ) ;
4151
4180
}
4152
4181
4153
4182
/**
4154
- * Creates a behavior property that references an immediate content child elememnt that matches the provided selector.
4183
+ * Creates a behavior property that references an immediate content child element that matches the provided selector.
4155
4184
*/
4156
4185
export function child ( selectorOrConfig : string | Object ) : any {
4157
4186
return createChildObserverDecorator ( selectorOrConfig , false ) ;
0 commit comments