Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions tko.io/src/content/docs/3to4.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,30 @@ TKO is designed for stricter Content Security Policies and avoids the older `eva

`ko.applyBindings` returns a `Promise`. If you chain bootstrap work after binding or need to wait for async bindings to finish, account for that in your startup flow.

### `descendantsComplete` no longer waits for async descendants

In Knockout 3, `descendantsComplete` fired only after every descendant — including content rendered asynchronously by a nested `if`, `template`, `foreach`, or component — had finished binding. Knockout tracked this with an ancestor-linked async-completion context and, on control-flow bindings, a `completeOn: 'render'` option.

TKO drops that ancestor-tracking machinery in favor of a simpler per-node model. As a result, `descendantsComplete` is decided **once**, synchronously, when the node itself binds, and waits only for async bindings **on that same node** — not for subtrees that appear later. If a descendant `if`/`template` renders its content after the fact (for example when its condition flips to `true`), the `descendantsComplete` callback is not re-triggered.

**Why:** the async-completion context was cross-cutting, hard to reason about, and a common source of disposal and ordering bugs. The per-node lifecycle is smaller and predictable, at the cost of this one edge case.

**Migration:** use `childrenComplete` instead, which is notified every time a node's descendants are (re-)bound and therefore still fires when async content renders:

```html
<!-- Knockout 3: relied on descendantsComplete firing after nested async content -->
<div data-bind="if: ready, descendantsComplete: onReady">
<div data-bind="if: innerReady">…</div>
</div>
```

```html
<!-- TKO: move the callback to the node whose children you care about -->
<div data-bind="if: ready">
<div data-bind="if: innerReady, childrenComplete: onReady">…</div>
</div>
```

## What is still familiar

- `ko.observable`, `ko.observableArray`, and `ko.computed`
Expand Down
Loading