Skip to content
Playground llms.txt
Docs in progress TKO docs are in progress. Examples, API details, and migration notes are still being revised.

Loading & Saving Data

TKO doesn’t prescribe how you load or save data — use fetch, a library, or whatever your server expects. This page covers the patterns for moving data between your server and your observable view models.

Use ko.toJS to strip observables from a view model before sending it to a server:

const vm = {
firstName: ko.observable('Jane'),
lastName: ko.observable('Doe'),
tags: ko.observableArray(['admin', 'active'])
}
const save = async () => {
const data = ko.toJS(vm)
// data is { firstName: 'Jane', lastName: 'Doe', tags: ['admin', 'active'] }
await fetch('/api/user', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
}

Or use ko.toJSON as a shorthand for JSON.stringify(ko.toJS(...)):

await fetch('/api/user', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: ko.toJSON(vm)
})

When you receive data from a server, update each observable individually:

const load = async () => {
const response = await fetch('/api/user')
const data = await response.json()
vm.firstName(data.firstName)
vm.lastName(data.lastName)
vm.tags(data.tags)
}

For larger models, a helper keeps things tidy:

const updateFrom = (viewModel, data) => {
for (const [key, value] of Object.entries(data)) {
if (ko.isWritableObservable(viewModel[key])) {
viewModel[key](value)
}
}
}
// Usage
const load = async () => {
const data = await fetch('/api/user').then(r => r.json())
updateFrom(vm, data)
}

Bind ko.toJSON directly to see the live state of your view model:

<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

This updates in real time as observables change — useful during development.