Derived Value
Derived values are an automatic way to update your variable values based on changes to selected data. 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 }]);Using Derived Values
Section titled “Using Derived Values”To create a derived value, you can use the .derived() method of the NimbusDBModel class.
// (1) on this instance variablesapple_price = items.derived("apple_price", 1, "price");// the derived value refers to the "price" column of the data with primary key 1 in the "items" model// so, `apple_price` will be 5
item_names = [ "Apple", items.derived("item_names[1]", 2, "name"), items.derived("item_names.2", 3, "name") [ items.derived("item_names[2][0]", 4, "name") ]];
item_names[4] = items.derived("item_names[4]", 5, "name");
// (2) on global variables// add "global." or "g." prefix to mark it as global variableglobal.apple_name = items.derived("global.apple_price", 1, "name");
global.item_names = [ "Apple", items.derived("g.item_names[1]", 2, "name"), items.derived("global.item_names.2", 3, "name") [ items.derived("global.item_names[2][0]", 4, "name") ]];
// later, you can update the dataitems.update_by_primary(1, { name: "Bad Apple", price: 10});
// after updating the data, the derived value will be updated automatically// `apple_price` variable will be 10, `global.apple_name` will be "Bad Apple", etc.// works for arrays and objects tooDerived Value on Object Fields
Section titled “Derived Value on Object Fields”Using derived values on object fields need extra care, so you won’t get undefined value even if the data/method is used properly.
some_var = { normal: items.derived("some_var.normal", 1, "name"), arr: [items.derived("some_var.arr[0]", 1, "name")], nested: { price: items.derived("some_var.nested.price", 2, "price"), arr: [items.derived("some_var.nested.arr[0]", 2, "name")] }}
// if you access any field of `some_var` in this frame, you will get `undefined` valuevar item1_name = some_var.normal; // undefined// also happens for other fields under `some_var`var item2_name = some_var.arr[0];some_var = { // set a placeholder value first (any value is fine) normal: items.derived("some_var.normal", 1, "name"), arr: [items.derived("some_var.arr[0]", 1, "name")], normal: "", arr: [ undefined ], nested: { price: items.derived("some_var.nested.price", 2, "price"), arr: [items.derived("some_var.nested.arr[0]", 2, "name")] price: 0, arr: [ false ] }}
// set the derived value after object creation some_var.normal = items.derived("some_var.normal", 1, "name"); some_var.arr[0] = items.derived("some_var.arr[0]", 1, "name"); some_var.nested.price = items.derived("some_var.nested.price", 2, "price"); some_var.nested.arr[0] = items.derived("some_var.nested.arr[0]", 2, "name");
// if you access any field of `some_var` in this frame, you will get the correct valuevar item1_name = some_var.normal; // "Apple"Derived Value Options
Section titled “Derived Value Options”// (1) set a callback function to be called when the data is updated// set `on_update` option to enable thisapple_price = items.derived("apple_price", 1, "price", { on_update: function(data, new_val, old_val, prop) { show_debug_message($"`apple_price` has been updated to {new_val}"); }, immediate: true // in case you want to call the callback immediately after creation});
// (2) variable name shortening for nested objects// set `ref` option to enable thissome_var = { nested: { nested_again: { some_var: 0 } }}
// instead of this:some_var.nested.nested_again.some_var = items.derived("some_var.nested.nested_again.some_var", 1, "name");
// you can do this:some_var.nested.nested_again.some_var = items.derived("nested_again.some_var", 1, "name", { ref: some_var.nested});// or this:some_var.nested.nested_again.some_var = items.derived("some_var", 1, "name", { ref: some_var.nested.nested_again});Considerations
Section titled “Considerations”- Derived values only work on instance variables and global variables. So, local variables are not supported.
- Both
var_name[index]andvar_name.indexare supported for array. - You can use derived values on arrays up to 3D (i.e.
var_name[index][index][index]). - Object can contain arrays, but arrays can’t be nested inside objects.
obj = {normal: items.derived("obj.normal", 1, "name"),// arrays inside objects are supportedarr: [items.derived("obj.arr[0]", 1, "name")],nested: {arr: [items.derived("obj.nested.arr[0]", 2, "name")]}};arr = [items.derived("obj[0].normal", 1, "name"),[ items.derived("obj[1].arr[0]", 2, "name") ],// but objects inside arrays are not supported{ some_prop: items.derived("obj[0].some_prop", 1, "name") },{arr: [items.derived("obj[1].arr[0]", 2, "name")],nested: {arr: [items.derived("obj[1].nested.arr[0]", 3, "name")]}}]
References
Section titled “References”NimbusDBDerived Internal
Section titled “NimbusDBDerived ”The NimbusDBDerived class is used to define derived values in NimbusDB models.
class NimbusDBDerived { constructor( _inst_id: Instance | "global", _var_name: string, // use "global" or "g" prefix to use global variable _model: NimbusDBModel, _data: Struct, // from data _watch_column?: string | string[], _options?: NimbusDBDerivedConstOptions )
data: Struct; id: int; last_val: any; prop_name: string; var_name: string; // variable name in ref
on_update?: ( // called when the data is updated data: Struct, new_val: any, old_val: any, prop: string ) => void;
static refresh: () => void; static update: () => void;
static __id: int; __inst: Instance | "global"; __model: NimbusDBModel; __ref: Instance | Struct | "global"; // root reference __source?: NIMBUSDB_DERIVED.SOURCE_INSTANCE | NIMBUSDB_DERIVED.SOURCE_GLOBAL | NIMBUSDB_DERIVED.SOURCE_STRUCT; __target?: NIMBUSDB_DERIVED; // .TARGET_* __indexes?: int[]; __sys_temp?: Struct; __reinit_count: int;
static __init: () => void;}Model.derived()
Section titled “Model.derived()”Creates a derived value from watched model data.
Signature
Section titled “Signature”class NimbusDBModel { // ... other methods and properties ... static derived( _var_name: string, _original_data: int | NimbusDBData, _watch_column: string, _instance?: Instance ): any;}Parameters
Section titled “Parameters”_var_name
Section titled “_var_name”- Type:
string - The name of the variable to bind to.
_original_data
Section titled “_original_data”- Type:
int|NimbusDBData - The original model data reference (direct-access data) or primary key of the data.
_watch_column
Section titled “_watch_column”- Type:
string - The column to watch for changes.
_instance
Section titled “_instance”- Type:
Instance - The instance reference to bind the derived value to.
Returns
Section titled “Returns”- Type:
any - The value of a column from the related data.
Signature
Section titled “Signature”class NimbusDBModel { // ... other methods and properties ... static derived( _var_name: string, _original_data: int | NimbusDBData, _watch_column: string, _options?: NimbusDBDerivedOptions ): any;}Parameters
Section titled “Parameters”_var_name
Section titled “_var_name”- Type:
string - The name of the variable to bind to.
_original_data
Section titled “_original_data”- Type:
int|NimbusDBData - The original model data reference (direct-access data) or primary key of the data.
_watch_column
Section titled “_watch_column”- Type:
string - The column to watch for changes.
_options
Section titled “_options”- Type:
NimbusDBDerivedOptions - Default:
undefined - Optional configuration for the operation.
Returns
Section titled “Returns”- Type:
any - The value of a column from the related data.
NimbusDBDerivedConstOptions Internal
Section titled “NimbusDBDerivedConstOptions ”An optional configuration object for the NimbusDBDerived constructor.
type NimbusDBDerivedConstOptions = Partial<{ ref: Instance | Struct | "global"; // override NimbusDBModel.__root on_update: ( // called when the data is updated data: Struct, new_val: any, old_val: any, prop: string ) => void;}NimbusDBDerivedOptions
Section titled “NimbusDBDerivedOptions”An optional configuration object for the NimbusDBModel.derived() method.
type NimbusDBDerivedOptions = Partial<{ inst: Instance | "global"; // override NimbusDBDerived.__inst immediate: boolean; // call .on_update immediately after creation (default = false) ref: Instance | Struct | "global"; // override NimbusDBDerived.__sys_temp.ref return_id: boolean; // return the id of the data instead of the data (default = false) on_update: ( // called when the data is updated data: Struct, new_val: any, old_val: any, prop: string ) => void;}>;NIMBUSDB_DERIVED Internal
Section titled “NIMBUSDB_DERIVED ”An enum that defines the source and target of a derived value.
enum NIMBUSDB_DERIVED { SOURCE_INSTANCE = 1, SOURCE_GLOBAL, SOURCE_STRUCT, TARGET_INSTANCE = 1, TARGET_INSTANCE_ARRAY_1D, TARGET_INSTANCE_ARRAY_2D, TARGET_INSTANCE_ARRAY_3D, TARGET_GLOBAL_STRUCT, TARGET_GLOBAL_ARRAY_1D, TARGET_GLOBAL_ARRAY_2D, TARGET_GLOBAL_ARRAY_3D, TARGET_STRUCT, TARGET_STRUCT_ARRAY_1D, TARGET_STRUCT_ARRAY_2D, TARGET_STRUCT_ARRAY_3D}