Skip to content

Commit 359c960

Browse files
authored
fix(compose): properly handle replace strategy
1 parent 605a232 commit 359c960

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

src/compose.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,15 @@ function processChanges(composer: Compose) {
253253
const changes = composer.changes;
254254
composer.changes = Object.create(null);
255255

256-
if (needsReInitialization(composer, changes)) {
256+
const activationStrategy = determineActivationStrategy(composer);
257+
if (needsReInitialization(activationStrategy, changes)) {
258+
//when using `replace` activation strategy - we cant force the creation of a new VM
259+
const currentViewModel = activationStrategy === ActivationStrategy.Replace ? null : composer.currentViewModel;
260+
257261
// init context
258262
let instruction = {
259263
view: composer.view,
260-
viewModel: composer.currentViewModel || composer.viewModel,
264+
viewModel: currentViewModel || composer.viewModel,
261265
model: composer.model
262266
} as CompositionContext;
263267

@@ -302,13 +306,16 @@ function requestUpdate(composer: Compose) {
302306
});
303307
}
304308

305-
function needsReInitialization(composer: Compose, changes: any) {
309+
function determineActivationStrategy(composer: Compose): ActivationStrategy {
306310
let activationStrategy = composer.activationStrategy;
307311
const vm = composer.currentViewModel;
308312
if (vm && typeof vm.determineActivationStrategy === 'function') {
309313
activationStrategy = vm.determineActivationStrategy();
310314
}
315+
return activationStrategy;
316+
}
311317

318+
function needsReInitialization(activationStrategy: ActivationStrategy, changes: any): boolean {
312319
return 'view' in changes
313320
|| 'viewModel' in changes
314321
|| activationStrategy === ActivationStrategy.Replace;

test/compose.integration.spec.ts

+10
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,14 @@ describe('compose.integration.spec.ts', () => {
8282
});
8383

8484
it('works with determineActivationStrategy() - replace', async () => {
85+
let constructorCount = 0;
8586
const { component, compose } = await bootstrapCompose(
8687
`<compose view-model.bind="viewModel"></compose>`,
8788
{
8889
viewModel: class {
90+
constructor() {
91+
constructorCount++;
92+
}
8993
// w/o the get view strategy, the initial composition fails, which results to undefined currentViewModel
9094
getViewStrategy() {
9195
return new InlineViewStrategy('<template></template>');
@@ -104,18 +108,23 @@ describe('compose.integration.spec.ts', () => {
104108
compose.modelChanged({ a: 1 }, oldModel);
105109

106110
taskQueue.queueMicroTask(() => {
111+
expect(constructorCount).toBe(2, 'constructor count === 2');
107112
expect(compose.compositionEngine.compose).toHaveBeenCalledTimes(1);
108113
component.dispose();
109114
});
110115

111116
});
112117

113118
it('works with determineActivationStrategy() - invoke-lifecycle', async () => {
119+
let constructorCount = 0;
114120
let activationCount = 0;
115121
const { component, compose } = await bootstrapCompose(
116122
`<compose view-model.bind="viewModel"></compose>`,
117123
{
118124
viewModel: class {
125+
constructor() {
126+
constructorCount++;
127+
}
119128
activate() {
120129
activationCount++;
121130
}
@@ -138,6 +147,7 @@ describe('compose.integration.spec.ts', () => {
138147
compose.modelChanged({}, oldModel);
139148

140149
taskQueue.queueMicroTask(() => {
150+
expect(constructorCount).toBe(1, 'constructor count === 1');
141151
expect(activationCount).toBe(2, 'activation count === 2');
142152
component.dispose();
143153
});

0 commit comments

Comments
 (0)