When working with components, which aren't of a primitive type (e.g. records), it is best practice to create Typescript interfaces for easier access to the columns/properties.
interface MyRecord {
Key: number;
Column1: string;
Column2: number;
//...
}
While Hive itself is case-insensitive, accessing object properties in Javascript isn't. That means MyRecord.CoLuMn1
would work in Hive, but not in CustomJS! This is not only a bit uncomfortable for the developer but can also lead to errors due to the caching behaviour of Hive.
A little casing typo which is corrected afterwards
MYTexT=Text
MyText=Text
afterwardsAfter this you can already see a difference between the Record-Editor and the Result-View.
Hive is case-insensitive and works as intended:
Javascript can only use it with one specific definition.
The logical approach of the developer would be, to create an interface with the correct/latest casing.
But this won't work because it's already cached with the 'wrong' (initial) casing.
interface TestRecord {
Key: string;
MyText: string; // doesn't work
// MyTexT: string; // would work (cached property-name)
}
In order to solve this issue, it is now mandatory to register every interface at runtime, so that it can be matched in a case-insensitive manner. When component data is retrieved with one of the intended functions (e.g.: CmpUtils.getRecordCmpValue) the object will be automatically altered, so that the casing is identical to the one from the interface.
This requires the following steps (already part of the examples projects .template-project
or custom-js-4-partners
):
Add webpack-plugin to automatically convert interfaces in typings/*.hive.d.ts
to js-objects
Start a watch/build-process to convert these files
Import the converted file in your CJS-project
Call the register-function
Although this might seem like many additional steps, it only has to be done once when used as intended and it improves the code quality and project structure. See usage below.
Component Name Colors
{
{ Key=Text, Name=Text, HexCode=Text, Price=Number, Roughness=Number, Metallic=Number }
{ "Bl1" , "Black" , "#171C28" , 1600 , 0 , 0.8 }
}
./src/typings/cbn-car-typings.hive.d.ts
interface ColorsRecord {
Key: number;
Name: string;
HexCode: string;
Roughness: number;
Metallic: number;
}
// Column "Price" isn't required in CJS
./src/typings-generated-objs/cbn-car-typings.hive.d-ti.js
-> The webpack plugin automatically creates/updates this file whenever the content of cbn-car-typings.hive.d.ts
is changed.
import HiveTypings from './typings-generated-objs/cbn-car-typings.hive.d-ti';
// Interface 'ColorsRecord' should match with cmp 'Colors'
CmpUtils.registerInterfaceSuite(HiveTypings, {
namePostfix: 'Record',
mappings: { [CmpNames.SecondaryColor]: HiveTypings.ColorsRecord },
});
CfgrUtils.onCfgrReady(() => {
// Possible case mismatches are now automatically fixed due the call to `registerInterfaceSuite` above
const color = /** @type {ColorsRecord} */ (CmpUtils.getRecordCmpValue(CmpNames.Colors));
console.log(color.HexCode);
// Value-Cmp which uses the same interface (see `mappings` above)
const secColor = /** @type {ColorsRecord} */ (CmpUtils.getCmpValue(CmpNames.SecondaryColor));
});
Each record which is accessed from a CJS project has to be assigned to a corresponding interface. For easier usage this can be done with a whole interface-file at once.
The interfaces for all required records can be created in one file or seperated in different ones. Requirements:
./src/typings/
*.hive.d.ts
It's not mandatory to create a property for every record column. Columns which are never touched in CJS can simply be omitted.
// Record: Key=Number, Name=Text, Address=Text, City=Text
interface MyRecord {
Key: number;
Name: string;
}
It's possible to add optional properties to the interface, if you want to store additional data for the record in CJS.
Simply add a ?
after the key of your property to make it optional.
interface MyRecord {
Key: number;
Name: string;
CustomCjsValue?: string;
}
Import the generated files from the folder /typings-generated-objs/
and pass the imported object to the register-function.
For details see CmpUtils.registerInterfaceSuite and its options Cbn.CJS.CmpInterfaceSuiteOptions.
CustomJSCmps
. Specific issues or errors related to the interface itself might stay unnoticed until it is retrieved the first time. Therefore check for any warnings or errors in the console during development.
Since v6.0.0 value-components, which aren't of a primitive type, are also automatically parsed to objects. This makes it necessary to register interfaces for them as well. If one or more value-components retrieve data from a record-component or some kind of "BaseObject" it's recommended to define the interface with its "most basic name" and map other components to this type or derive from it.
// typings/index.hive.d.ts
interface FurnitureRecord {
id: number;
name: string;
}
type SelectedFurniture = FurnitureRecord[];
// cfgr-main.js
CmpUtils.registerInterfaceSuite(HiveCmpItf, {
namePostfix: 'Record',
mappings: {
[CmpNames.Chairs]: HiveCmpItf.FurnitureRecord,
[CmpNames.Tables]: HiveCmpItf.FurnitureRecord,
[CmpNames.SelectedFurniture]: HiveCmpItf.SelectedFurniture, // Value-Cmp
},
});
Additional info: Cbn.CJS.CmpInterfaceSuiteOptions.mappings
To register an array it's required to do the typing with the type
keyword instead of interface
.
interface Element {
id: number;
name: string;
}
type ElementList = Element[];
// OR
type Elements = Element[];
Shortcut if the single Element
isn't required:
type ElementList = {
id: number;
name: string;
}[];
Project folder
package.json
for installed packages (see .template-project
or custom-js-4-partners
)ts-interface-checker
ts-interface-builder
npm i
inside the project folderRoot folder
package.json
for installed packages@combeenation/webpack-hive-itf-to-obj-plugin
master
npm i
inside the root folder/typings-generated-objs/
aren't created./src/typings/
with the extension *.hive.d.ts
It might happen that the watch process doesn't detect the changes from the auto-generated file.
Generated using TypeDoc