Skip to content

Commit

Permalink
fix(compose): properly handle replace strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
avrahamcool authored Jan 23, 2024
1 parent 605a232 commit 359c960
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 3 deletions.
13 changes: 10 additions & 3 deletions src/compose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,15 @@ function processChanges(composer: Compose) {
const changes = composer.changes;
composer.changes = Object.create(null);

if (needsReInitialization(composer, changes)) {
const activationStrategy = determineActivationStrategy(composer);
if (needsReInitialization(activationStrategy, changes)) {
//when using `replace` activation strategy - we cant force the creation of a new VM
const currentViewModel = activationStrategy === ActivationStrategy.Replace ? null : composer.currentViewModel;

// init context
let instruction = {
view: composer.view,
viewModel: composer.currentViewModel || composer.viewModel,
viewModel: currentViewModel || composer.viewModel,
model: composer.model
} as CompositionContext;

Expand Down Expand Up @@ -302,13 +306,16 @@ function requestUpdate(composer: Compose) {
});
}

function needsReInitialization(composer: Compose, changes: any) {
function determineActivationStrategy(composer: Compose): ActivationStrategy {
let activationStrategy = composer.activationStrategy;
const vm = composer.currentViewModel;
if (vm && typeof vm.determineActivationStrategy === 'function') {
activationStrategy = vm.determineActivationStrategy();
}
return activationStrategy;
}

function needsReInitialization(activationStrategy: ActivationStrategy, changes: any): boolean {
return 'view' in changes
|| 'viewModel' in changes
|| activationStrategy === ActivationStrategy.Replace;
Expand Down
10 changes: 10 additions & 0 deletions test/compose.integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,14 @@ describe('compose.integration.spec.ts', () => {
});

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

taskQueue.queueMicroTask(() => {
expect(constructorCount).toBe(2, 'constructor count === 2');
expect(compose.compositionEngine.compose).toHaveBeenCalledTimes(1);
component.dispose();
});

});

it('works with determineActivationStrategy() - invoke-lifecycle', async () => {
let constructorCount = 0;
let activationCount = 0;
const { component, compose } = await bootstrapCompose(
`<compose view-model.bind="viewModel"></compose>`,
{
viewModel: class {
constructor() {
constructorCount++;
}
activate() {
activationCount++;
}
Expand All @@ -138,6 +147,7 @@ describe('compose.integration.spec.ts', () => {
compose.modelChanged({}, oldModel);

taskQueue.queueMicroTask(() => {
expect(constructorCount).toBe(1, 'constructor count === 1');
expect(activationCount).toBe(2, 'activation count === 2');
component.dispose();
});
Expand Down

0 comments on commit 359c960

Please sign in to comment.