Skip to content

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 }
]);

Before we dive into how to use computed data, let’s briefly compare it with watchers and derived data:

FeatureComputedWatcherDerived
PurposeTo compute a value based on certain dataTo execute custom logic after data changesTo get a value based on certain data
Return ValueYes (the computed object)NoYes (the value of target property)
Getting ValueAccess the .value property manually from the computed objectN/AThe target variable is automatically updated and can be accessed directly
Callback FunctionYes (getter function)Yes (watcher callback)No
Execution TimingExecuted 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)
ReactivityAutomatically updates when any column of the original data changesExecutes when the target column(s) changeAutomatically updates when the target column changes
Use CaseWhen you want to compute a value based on the entire data and execute custom logic after the data is updatedWhen you want to execute custom logic after specific column(s) of the data are updatedWhen you want to get a value based on specific column(s) of the 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 data
var 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 value
var old_apple_price = apple_price_comp.value; // undefined, because the data hasn't been updated yet
// create a computed value from model data
var 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 value
var old_apple_price = apple_price_comp.value; // 5
// update the apple price
items.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 value
var new_apple_price = apple_price_comp.value; // 6

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 function
some_var = 2.75;
discount = 0.2;
// define the getter function
var 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 data
var banana_discounted_price_comp = items.computed(2, banana_price_getter, {
immediate: true // call the getter function immediately after creation
});
// get the computed value
var old_banana_discounted_price = banana_discounted_price_comp.value; // 5.76
// update the banana price
items.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 value
var new_banana_discounted_price = banana_discounted_price_comp.value; // 7.52

The NimbusDBComputed class is used to define computed data in NimbusDB models.

reactivity.d.ts
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;
}

Creates a computed value from model data.

model.d.ts
class NimbusDBModel {
// ... other methods and properties ...
static computed(
_original_data: int | NimbusDBData,
_getter: (data: Struct) => any,
_option?: NimbusDBComputedOptions
): NimbusDBComputed | null;
}
  • Type: int | NimbusDBData
  • The original model data reference (direct-access data) or primary key of the data.
  • Type: (data: Struct) => any
    • Parameters:
      • data: The data to compute.
    • Returns:
      • The computed value.
  • The getter callback used to compute the derived value.
  • Type: NimbusDBComputedOptions
  • Default: undefined
  • Optional configuration for the operation.
  • Type: NimbusDBComputed | null
  • The computed binding when it can be created, or null if the operation cannot be completed.

An optional configuration object for the NimbusDBModel.computed() method.

reactivity.d.ts
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)
}>;

A type that represents a listener for all reactive data-binding.

reactivity.d.ts
type NimbusDBListener =
| NimbusDBComputed
| NimbusDBWatcher
| NimbusDBDerived
;