Field Delegates

Sometimes you don't want the whole document — just one field, read and written like an ordinary Kotlin property. Field delegates give you that without giving up typed, reactive storage.

class NoteEditor {
    private val note = Documents.document<Note>("note-1")

    var done: Boolean by note.field(Note::done, default = false)
    val doneFlow: Flow<Boolean> = note.fieldFlow(Note::done, default = false)
}

field(prop, default)

field(prop, default) returns a ReadWriteProperty backed by a single decomposed key. Reading it returns default if the field was never set; writing it updates only that field's key — nothing else about the document is touched — and emits on the document's flow() too:

editor.done = true   // writes only the "done" field's key
println(editor.done) // reads only that key

Why the caller supplies default

A field's declared default isn't recoverable from a KProperty at runtime, so field() and fieldFlow() both take default explicitly — there's no reflection-based way to ask "what was the default value of this property in the data class?" once you're holding a bare property reference.

fieldFlow(prop, default)

Emits the current field value (or default, if never set) on collection, then a new value each time that field changes. A change to a sibling field stays quiet:

note.fieldFlow(Note::done, default = false).collect { done ->
    checkbox.setChecked(done)
}

Not inside a class with a delegate? Use update(prop, value)

For a one-off field write with no delegate to declare, plain note.update(Note::done, true) does the same single-key write directly — see Read & Write. It's the non-delegate sibling to field(), for code that doesn't own a var-backed property.

When to reach for this

Field delegates suit settings-style usage — a screen with a handful of independent toggles or values, each bound directly to a property, with no need to read or write the rest of the document. See Settings & Preferences for a fuller example.