Observable Objects
An HsObservable publishes changes to its decorated fields. A BaseView can
observe the object and rebuild when those fields change.
Define an observable
Extend HsObservable and decorate each published property:
import { HsObservable } from '@hs-src/hosanna-ui/hosanna-api';
import { observableField } from '@hs-src/hosanna-ui/lib/decorators';
export class CounterModel extends HsObservable {
@observableField
count = 0;
@observableField
name = 'John Doe';
}
Assignments notify only when the value changes. Use
@observableField(true) only when duplicate assignments must also notify.
Observe a view property
Use @observable() for an object owned by or passed into a view:
export class CounterScreenView extends BaseView<CounterScreenState> {
@observable()
counter = new CounterModel();
protected override getViews() {
return [
Label({ text: `Count: ${this.counter.count}` }),
Button({ text: 'Increment' })
.onClick(() => this.counter.count++),
];
}
}
Pass a field list to limit invalidation:
@observable(['count'])
counter = new CounterModel();
With no list, the decorator observes __internalState, which receives changes
from all decorated model fields.
Change observable fields from input handlers, lifecycle methods, or async
completion callbacks—not from getViews().
Inject a shared observable
Register the instance, then use the supported @injectObservable() decorator:
AppUtils.register('counter', counter);
export class SummaryScreenView extends BaseView<SummaryScreenState> {
@injectObservable('counter', ['count'])
counter!: CounterModel;
}
@injectObservable both resolves the IoC key and wires observation. Use
@observable() instead when the object arrives as view state or is constructed
by the view.
Filter an update in a view
A view can inspect observable notifications before Hosanna invalidates it:
protected override onObservableFieldUpdated(
observableFieldName: string,
field?: string,
): boolean {
if (observableFieldName === 'counter' && field === 'name') {
return false;
}
return true;
}
Return false only when that update cannot affect the rendered structure.
Manual observation
Prefer the decorators for normal view rendering. Lower-level integrations can
call addObserver() and removeObserver() directly—for example, when an
adapter updates a native renderer without rebuilding the view. Always remove a
manual observer when its owner stops listening.