# Au 2.0: Concerning au-compose, activate is called when the model is replaced, but deactivate is not called on the outgoing composition

**URL:** <https://discourse.aurelia.io/t/au-2-0-concerning-au-compose-activate-is-called-when-the-model-is-replaced-but-deactivate-is-not-called-on-the-outgoing-composition/6564>\
**Category:** Help Requests\
**Created:** [December 28, 2025, 4:18am UTC](https://discourse.aurelia.io/t/au-2-0-concerning-au-compose-activate-is-called-when-the-model-is-replaced-but-deactivate-is-not-called-on-the-outgoing-composition/6564 "2025-12-28T04:18:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![estaylorco](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/estaylorco/32/1887_2.png) [@estaylorco](https://discourse.aurelia.io/u/estaylorco)\
**Post date:** [December 28, 2025, 4:18am UTC](https://discourse.aurelia.io/t/au-2-0-concerning-au-compose-activate-is-called-when-the-model-is-replaced-but-deactivate-is-not-called-on-the-outgoing-composition/6564/1 "2025-12-28T04:18:32Z")

</div>

Hello,

I’m making some improvements to my tabbed viewer as I migrate from Au 1.0 1o Au 2.0.

As I click through the tabs, `activate` is called and **all is well** for the incoming component; `deactivate`, however, is not called on the outgoing component.

And, actually, only the model and session are being replaced. The component isn’t changing. I have this:

```xml
<div class="tsi-doc-viewer-view">
  <au-compose    
    component.bind="dm.activeDoc.docComponent"
    model.bind="dm.activeDoc.model"
    session.bind="dm.activeDoc.session"
  ></au-compose>
</div>

```

So, `dm.activeDoc.docComponent` doesn’t change. However, `dm.activeDoc.model` does. `session` is forwarded to the component composed.

**How can Aurelia reliably call activate when a new model is bound, but not call deactivate on the outgoing component?** I know I can take a component ref on the composition, and then imperatively call deactivate() on the component. But it seems like I shouldn’t have to do that. I don’t do that in the Au 1.0 app.

Did something change in 2.0?

---

<div class="post-metadata">

**Author:** ![dwaynecharrington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/dwaynecharrington/32/11_2.png) [@dwaynecharrington](https://discourse.aurelia.io/u/dwaynecharrington)\
**Post date:** [January 1, 2026, 10:49pm UTC](https://discourse.aurelia.io/t/au-2-0-concerning-au-compose-activate-is-called-when-the-model-is-replaced-but-deactivate-is-not-called-on-the-outgoing-composition/6564/2 "2026-01-01T22:49:24Z")

</div>

This is by design in Aurelia 2, and it’s actually an intentional optimisation.

In Au2’s `au-compose`, when only the model changes but the component stays the same:

1. `deactivate()` is NOT called on the existing component
2. `activate()` IS called again with the new model
3. The component instance is reused (no teardown/recreation)

This is a lightweight update path. Which you can see in the `au-compose.ts` source code from the main au2 repo:

`if (name === ‘model’ && this._composition != null) {`  
`this._composition.update(this.model); // Just calls activate(model) again`  
`return; // No recomposition`  
`}`

The `update()` function internally just calls `comp.activate?.(model)` on the existing instance.

It avoids unnecessary teardown/setup cycles when only the data changes. The same component instance handles multiple models sequentially.

How to adapt your code:

Your `activate()` method should handle being called multiple times with different models. If you need cleanup logic when switching between models, do it at the beginning of `activate()`:

```auto
activate(model: MyModel) {
// Cleanup from previous model (if any)
this.cleanupPreviousState();

// Set up for new model
this.currentModel = model;
this.initializeForModel();

}

```

Alternatively, if you truly need deactivate semantics, you could:

1. Use `@watch` on the model to detect changes
2. Implement a custom `modelChanged()` lifecycle callback that performs cleanup

This differs from Au1 where the compose element would fully recompose on model changes, triggering the full lifecycle. Au2’s approach is more performant but requires this pattern adjustment.

---

<div class="post-metadata">

**Author:** ![estaylorco](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/estaylorco/32/1887_2.png) [@estaylorco](https://discourse.aurelia.io/u/estaylorco)\
**Post date:** [January 2, 2026, 12:31am UTC](https://discourse.aurelia.io/t/au-2-0-concerning-au-compose-activate-is-called-when-the-model-is-replaced-but-deactivate-is-not-called-on-the-outgoing-composition/6564/3 "2026-01-02T00:31:44Z")

</div>

Hello Dwayne,

You know, I read your post before I went to dinner, and as I was eating, I realized what was going on. Since the composition isn’t changing (or, should I say, the component), we’re right there: the instance of the component is live and just right there.

And it definitely is blazing fast! I’m rewriting the tabbed viewer for Au 2.0, and it was so fast, I thought nothing was changing (my test harness uses project names that vary only slightly)!

It struck me that you and I might be using the term “deactivate” differently. I mean it as a hook strictly in symmetry with `activate`, and specifically for dynamic composition. I know when I call `deactivate` on an enhancement, it triggers a full tear-down (at least I think), and I’m not referring to that level of deactivation.

I disagree a bit on the absence of `deactivate`. It provides a logical place for that code to live. And if `activate` is lightweight, then surely `deactivate` would be, too (distinct from a full teardown). Whether I’m calling clean-up code imperatively out of `activate`, or in response to a change handler on `model`, I still have to call it, and consequently the hit to performance will be same in any case. Referring to the framework code you provided, would this change truly affect performance:

```javascript
if (name === ‘model’ && this._composition != null) {
this._composition.cleanUp() // Called before the update
this._composition.update(this.model); // Just calls activate(model) again
return; // No recomposition
}

```

Where the code inside #cleanUp might look like this:

```javascript
comp.deactivate?.(this.model) 

```

I think your suggestions as to how to deal with deactivate are all excellent, of course, and I’ll implement one of the approaches for sure (as I really need to). But the suggestions highlight an issue: without a deactivate hook, clean-up code might be implemented a number of different ways, and all to overcome the absence of a deactivate hook.
