Computed Data
A computed value, as the name suggests, is a value that’s computed/processed automatically based on the data it depends on. We’ll use this schema and items model for demonstration:
var schema = { id: { type: NIMBUSDB_DATA_TYPE.INTEGER, const: NIMBUSDB_CONSTRAINT.PRIMARY_KEY }, name: NIMBUSDB_DATA_TYPE.STRING, price: { type: NIMBUSDB_DATA_TYPE.NUMBER, validator: function(data, value) { return value >= 0; }, default_value: 0 }, is_locked: { type: NIMBUSDB_DATA_TYPE.BOOLEAN, const: NIMBUSDB_CONSTRAINT.OPTIONAL, default_value: false }};
items = new NimbusDBModel("global", "items", schema, [ { id: 1, name: "Apple", price: 5 }, { id: 2, name: "Banana", price: 7.2 }, { id: 3, name: "Cherry", price: 15 }, { id: 4, name: "Date", price: 12.5 }, { id: 5, name: "Elderberry", price: 8 }, { id: 6, name: "Fig", price: 10 }, { id: 7, name: "Grape", price: 6 }, { id: 8, name: "Honeydew", price: 9 }, { id: 9, name: "Kiwi", price: 4 }, { id: 10, name: "Lemon", price: 3 }]);Computed vs Watcher vs Derived
Section titled “Computed vs Watcher vs Derived”Before we dive into how to use computed data, let’s briefly compare it with watchers and derived data:
| Feature | Computed | Watcher | Derived |
|---|---|---|---|
| Purpose | To compute a value based on certain data | To execute custom logic after data changes | To get a value based on certain data |
| Return Value | Yes (the computed object) | No | Yes (the value of target property) |
| Getting Value | Access the .value property manually from the computed object | N/A | The target variable is automatically updated and can be accessed directly |
| Callback Function | Yes (getter function) | Yes (watcher callback) | No |
| Execution Timing | Executed when the original data is updated (once per update) | Executed after the target column(s) of the data are updated (can be executed multiple times per update if multiple columns are being watched) | Executed when the target column of the data is updated (once per update) |
| Reactivity | Automatically updates when any column of the original data changes | Executes when the target column(s) change | Automatically updates when the target column changes |
| Use Case | When you want to compute a value based on the entire data and execute custom logic after the data is updated | When you want to execute custom logic after specific column(s) of the data are updated | When you want to get a value based on specific column(s) of the data |
Using Computed Data
Section titled “Using Computed Data”To create a computed value, you can use the .computed() method of the NimbusDBModel class. This method returns a NimbusDBComputed object that you can use to access the computed value and listen for changes.
// create a computed value from model datavar apple_price_comp = items.computed(1, function(data) { // your custom logic here, for example: show_debug_message($"Apple price has been updated to {data.price}"); return data.price;});
// get the computed valuevar old_apple_price = apple_price_comp.value; // undefined, because the data hasn't been updated yet
// create a computed value from model datavar apple_price_comp = items.computed(1, function(data) { // your custom logic here, for example: show_debug_message($"Apple price has been updated to {data.price}"); return data.price;}, { immediate: true // call the getter function immediately after creation});
// get the computed valuevar old_apple_price = apple_price_comp.value; // 5
// update the apple priceitems.update_by_primary(1, { price: 6 });// you'll see the "Apple price has been updated to 6" message in the console/output
// get the new computed valuevar new_apple_price = apple_price_comp.value; // 6With Closures
Section titled “With Closures”You can also use closures to create computed values. This is useful when you need to access the computed value from outside the scope of the getter function.
// these variables are defined outside the scope of the getter functionsome_var = 2.75;discount = 0.2;
// define the getter functionvar banana_price_getter = function(data) { var discounted_price = data.price * (1 - discount); some_var = discounted_price / 2; // in case you want to modify the external variable
show_debug_message($"Banana price has been updated to {discounted_price} ({discount * 100}% discount)"); return discounted_price;}
// create a computed value from model datavar banana_discounted_price_comp = items.computed(2, banana_price_getter, { immediate: true // call the getter function immediately after creation});
// get the computed valuevar old_banana_discounted_price = banana_discounted_price_comp.value; // 5.76
// update the banana priceitems.update_by_primary(2, { price: 9.45 });// you'll see the "Banana price has been updated to 7.52 (20% discount)" message in the console/output
// get the new computed valuevar new_banana_discounted_price = banana_discounted_price_comp.value; // 7.52References
Section titled “References”NimbusDBComputed Internal
Section titled “NimbusDBComputed ”The NimbusDBComputed class is used to define computed data in NimbusDB models.
class NimbusDBComputed { constructor( _inst_id: Instance, _original_data: Struct, _getter: (data: Struct) => any );
id: int; value: any; // default = undefined
static refresh( _col: string, _idx: int ): void; static update(): void;
static __id: int; __data: Struct; __inst: Instance; __last_vals: any[]; __model: NimbusDBModel; __watch_columns: string[];
__callback: ( data: Struct, new_val: any, old_val: any, prop: string ) => void;}Model.computed()
Section titled “Model.computed()”Creates a computed value from model data.
Signature
Section titled “Signature”class NimbusDBModel { // ... other methods and properties ... static computed( _original_data: int | NimbusDBData, _getter: (data: Struct) => any, _option?: NimbusDBComputedOptions ): NimbusDBComputed | null;}Parameters
Section titled “Parameters”_original_data
Section titled “_original_data”- Type:
int|NimbusDBData - The original model data reference (direct-access data) or primary key of the data.
_getter
Section titled “_getter”- Type:
(data: Struct) => any- Parameters:
data: The data to compute.
- Returns:
- The computed value.
- Parameters:
- The getter callback used to compute the derived value.
_option
Section titled “_option”- Type:
NimbusDBComputedOptions - Default:
undefined - Optional configuration for the operation.
Returns
Section titled “Returns”- Type:
NimbusDBComputed|null - The computed binding when it can be created, or
nullif the operation cannot be completed.
NimbusDBComputedOptions
Section titled “NimbusDBComputedOptions”An optional configuration object for the NimbusDBModel.computed() method.
type NimbusDBComputedOptions = Partial<{ inst: Instance | "global"; // override NimbusDBComputed.__inst immediate: boolean; // call .update() immediately after creation (default = false) global: boolean; // use global variable as reference, override __inst (default = false)}>;NimbusDBListener Internal
Section titled “NimbusDBListener ”A type that represents a listener for all reactive data-binding.
type NimbusDBListener = | NimbusDBComputed | NimbusDBWatcher | NimbusDBDerived;