26. x0-Object Modeling
The following sections explain how to design custom x0-system-objects and define their specifications for seamless integration into the core system.
26.1. Basic Modeling Rules
Before proceeding, ensure you have a solid understanding of the following x0 fundamentals:
Base Classes / Inheritance
Child Objects / Parent Object
Event Handlers / Callbacks
Building Object Structure (DOM)
Modifying Runtime Data
Object Realtime Updates
Object Initialization
Adding Context Menu Functionality
26.2. Base Classes / Inheritance
The x0-framework follows a strict object-oriented approach. All custom x0-system-objects
must inherit from sysBaseObject
in their prototypes.
//- Inherit sysBaseObject
sysObjNewcomer.prototype = new sysBaseObject();
Refer to: 21.1. Base OOP Inheritance Model for more information on the x0 Core Base Model.
26.3. Child Objects / Parent Object
The this.ChildObjects[]
array in sysBaseObject.js
is used to manage child objects
of a sysBaseObject
instance. It acts as a recursive container, enabling hierarchical
object structures.
26.3.1. Initialization
In a custom object’s constructor, initialize this.ChildObjects[]
as an empty array:
this.ChildObjects = new Array(); //- Child Objects
26.3.2. Child-Parent Relationships
Each child object in the array is an instance of sysBaseObject
or its derived classes.
A parent-child relationship is established using the ParentObject
property.
//- Do something in the ParentObject
this.ParentObject.doSomething();
//- Do something in the ParentObject.ParentObject
this.ParentObject.ParentObject.doSomething();
26.3.3. Adding Child Objects
Adding objects to a parent object is straightforward:
//- add new sysObjDiv()
let Obj1 = new sysObjDiv();
Obj1.ObjectID = 'MyDiv1';
//- add Obj1 to parent
this.addObject(Obj1);
Refer to: 22.1. sysBaseObject.addObject for more details.
26.3.4. Rendering Child Objects
To propagate changes to the DOM, render all child objects:
//- Render all ParentObject.ChildObjects[]
this.ParentObject.renderObject();
26.4. Object Constructors
//------------------------------------------------------------------------------
//- CONSTRUCTOR "sysObjNewcomer"
//------------------------------------------------------------------------------
function sysObjNewcomer()
{
this.DOMType = 'button' //- Optional, default: 'div'
this.DOMAttributes = new Object(); //- Optional, add DOM attributes
this.EventListeners = new Object(); //- Optional
this.ChildObjects = new Array(); //- Always required
}
//- Inherit sysBaseObject
sysObjNewcomer.prototype = new sysBaseObject();
//- Inherit additional
sysObjNewcomer.prototype.SomeOverloadedMethod = sysObjectXyz.prototype.processSourceObjects;
26.4.1. DOMType
Override the this.DOMType
property directly within the constructor (default: ‘div’).
For example, setting this.DOMType = 'button'
will generate the HTML code <button></button>
.
26.4.2. DOMAttributes
By setting additional DOMAttributes:
this.DOMType = 'button';
this.DOMAttributes = { "attr1": "value1", "attr2": "value2" };
The resulting HTML will be rendered as: <button attr1="value1" attr2="values"></button>
.
26.4.3. EventListeners
Refer to 26.5. Event Handler / Callbacks.
26.4.4. ChildObjects
Refer to 26.3. Child Objects / Parent Object.
26.4.5. Inherit sysBaseObject
Always inherit sysBaseObject
; failing to do so will cause your object to malfunction.
26.4.5. Inherit Additional Methods
It’s up to you how to intelligently prototype or decorate your object using existing or custom object code.
26.5. Event Handler / Callbacks
Event handlers allow objects to process native DOM events. All event listeners
must be defined in the this.EventListeners[]
array.
26.5.1. Initialize Event Listeners
In the constructor, initialize this.EventListeners[]
as an empty array:
this.EventListeners = new Array(); //- Array of EventListener Objects
26.5.2. Adding Event Listeners
Add event listeners by defining their type and callback function:
let EventListenerObj = new Object();
EventListenerObj['Type'] = 'mousedown'; //- Event Type 'mousedown'
EventListenerObj['Element'] = this.EventListenerCallback.bind(this); //- Callback Method
this.EventListeners['ListenerID'] = EventListenerObj; //- Add Listener with ListenerID
26.5.3. Activating Event Listeners
To activate added event listeners:
this.processEventListener();
26.6. Building DOM Object Structure
Refer to: 27. Application Porting for detailed instructions on building DOM object structures.
26.7. Modifying Runtime Data
The following methods enable runtime data updates for x0-objects:
XML-RPC Async Call: Fetches data asynchronously from remote services.
RuntimeSetData(data): Updates the object’s current data.
RuntimeAppendData(data): Appends new data to the existing dataset.
26.8. Working With Realtime Objects
For realtime objects, removing DOM nodes is often more efficient than complex recursive updates. The x0-framework provides multiple methods:
26.8.1. remove()
Inherited from sysBaseObject
, this method removes the object from
ParentObject.ChildObjects[]
and deletes its corresponding DOM node.
Refer to: 27. Application Porting.
26.8.2. removeParent()
Also inherited from sysBaseObject
, this method removes the parent
object and all its child objects from the DOM.
Refer to: 22.4. sysBaseObject.removeParent for further details.
26.9. Object Loading / Initialization
Objects registered with the x0-core system expose the following properties:
26.9.1. init()
The init()
method is called during x0 system initialization (on page load).
Use this method to define initialization logic.
26.9.2. JSONConfig.Attributes
The object’s JSON configuration is processed during system initialization and applies
throughout its lifecycle. Use JSONConfig.Attributes
to define configuration data.
26.11. Object Registration
After object-modeling has been finished, it must be added to the x0-system.
26.11.1. User Object Runtime Import
Refer to: 7.6. Object Templates.
26.11.2. System Core Object
Register core x0-system-objects in sysFactory.js
by adding them to
sysFactory.SetupClasses
:
this.SetupClasses = {
"NewObjectType": sysNewObjectType,
}
A core x0-system-object should be included in /python/Index.py
as well.
26.12. Additional Examples
Check additional realtime processing code in the following system files:
sysRTPagination.js
sysRTFormSectionHeader.js
26.13. Building an Object Like sysObjDynRadioList.js
This section explains how to create a dynamic system object similar to
sysObjDynRadioList.js
in the x0-framework. It focuses on the structure,
methods, and key principles used in sysObjDynRadioList
.
26.13.1. Overview
The sysObjDynRadioList
is a dynamic object designed to manage a list of
radio buttons, with rows that can be added or removed at runtime. Each row
includes a radio button, an input field, and associated controls.
26.13.2. Key Components
- Base Object Inheritance:
Inherits from
sysBaseObject
for core functionality.
- Dynamic Rows:
Rows are represented by
sysObjDynRadioListRow
, which also inherits fromsysBaseObject
.
- Callbacks and Events:
Used for adding/removing rows and handling user interactions.
- JSON Configuration:
Utilized for defining object attributes and styles.
26.13.3. Step-by-Step Guide
Following, a Step-by-Step Guide, guiding you through the creation process.
26.13.4. Create the Base Class
Start by defining your main object, inheriting from sysBaseObject:
function sysObjDynRadioList() {
this.EventListeners = {};
this.ChildObjects = [];
this.RowItems = []; // Array to hold rows
this.RowIndex = 0; // Tracks row indices
}
// Inherit from sysBaseObject
sysObjDynRadioList.prototype = new sysBaseObject();
26.13.5. Initialize the Object
Define the init method to set up the object structure and default components:
sysObjDynRadioList.prototype.init = function() {
this.DOMType = 'div';
this.DOMStyle = 'container-fluid';
// Add an "Add Row" button
let AddButton = new sysObjButtonCallback();
AddButton.setCallback(this, 'add');
let AddButtonJSONAttributes = {
"DOMType": "a",
"Style": "col-md-1 btn btn-primary btn-sm",
"IconStyle": "fa-solid fa-plus",
"TextID": "TXT.BUTTON.ADD"
};
this.addObject(
new sysObjDynRadioListRow(
this, // Parent Object
false, // Context Menu disabled
AddButton, // Button Reference
AddButtonJSONAttributes // Button Attributes
)
);
};
26.13.6. Define the Row Class
Each row in the list is represented by sysObjDynRadioListRow
. This class manages its
elements (radio button, input field, and optional remove button):
function sysObjDynRadioListRow(ParentObject, CtxtMenu, ButtonRef, ButtonJSONAttr, SetRemoveCallback) {
this.EventListeners = {};
this.ChildObjects = [];
this.ParentObject = ParentObject;
this.Index = this.ParentObject.RowIndex;
this.CtxtMenuActive = CtxtMenu;
this.ButtonRef = ButtonRef;
this.ButtonJSONAttr = ButtonJSONAttr;
this.SetRemoveCallback = SetRemoveCallback;
this.init();
}
// Inherit from sysBaseObject
sysObjDynRadioListRow.prototype = new sysBaseObject();
sysObjDynRadioListRow.prototype.init = function() {
this.DOMStyle = 'row';
this.ObjectID = 'row-ctain' + this.ParentObject.ObjectID + this.Index;
this.RadioGroupID = 'row-ctain' + this.ParentObject.ObjectID;
// Add objects (radio button, input field, etc.)
this.addObjects(this.ButtonRef, this.ButtonJSONAttr);
// Set up callback for removing the row
if (this.SetRemoveCallback) {
this.ButtonRef.setCallback(this, 'remove');
}
// Add context menu listener if enabled
if (this.CtxtMenuActive) {
let EventListenerObj = {
'Type': 'mousedown',
'Element': this.EventListenerRightClick.bind(this)
};
this.EventListeners['ContextMenuOpen'] = EventListenerObj;
}
};
26.13.7. Add Rows Dynamically
The add method in sysObjDynRadioList
creates new rows dynamically:
sysObjDynRadioList.prototype.add = function() {
this.RowIndex += 1;
let RemoveButton = new sysObjButtonCallback();
let RemoveButtonJSONAttributes = {
"DOMType": "a",
"Style": "col-md-1 btn btn-primary btn-sm",
"IconStyle": "fa-solid fa-minus",
"TextID": "TXT.BUTTON.REMOVE"
};
this.addObject(
new sysObjDynRadioListRow(
this, // Parent Object
true, // Context Menu enabled
RemoveButton, // Button Reference
RemoveButtonJSONAttributes, // Button Attributes
true // Enable remove callback
)
);
// Re-render the object
this.renderObject(this.DOMParentID);
};
26.13.8. Handle Row Removal
The remove method in sysObjDynRadioListRow is used to remove a row:
sysObjDynRadioListRow.prototype.remove = function() {
this.removeBase(); // Call inherited remove method
};
In the parent object, the remove method manages the array of rows:
sysObjDynRadioList.prototype.remove = function(RowIndex) {
this.RowItems[RowIndex].remove();
};
26.13.9. Define Object Structure
Use the addObjects
method to define the DOM structure for each row:
sysObjDynRadioListRow.prototype.addObjects = function(ButtonRef, ButtonJSONAttributes) {
let ObjDefs = [
{
"id": "col-ctnt" + this.Index,
"SysObject": new sysObjDiv(),
"JSONAttributes": { "Style": "col-md-11" },
"ObjectDefs": [
{
"id": "base-ctain" + this.Index,
"SysObject": new sysObjDiv(),
"JSONAttributes": { "Style": "input-group" },
"ObjectDefs": [
{
"id": "radio-ctain" + this.Index,
"SysObject": new sysObjDiv(),
"JSONAttributes": {
"Style": "input-group-text",
"Value": '<input type="radio" id="' + this.ObjectID + '-root" name="' + this.RadioGroupID + '" class="form-check-input mt-0">'
}
},
{
"id": "input-text" + this.ObjectID + this.Index,
"SysObject": new sysFormfieldItemText(),
"JSONAttributes": {
"Style": "form-control",
"Type": "text"
}
}
]
}
]
},
{
"id": "col-btn",
"SysObject": ButtonRef,
"JSONAttributes": ButtonJSONAttributes
}
];
sysFactory.setupObjectRefsRecursive(ObjDefs, this);
};
26.13.10. Conclusion
By following this guide, you can create dynamic objects similar to sysObjDynRadioList.js. The key is leveraging the x0 system’s object-oriented framework, callbacks, and JSON-based DOM configuration. You can extend this structure further based on your application’s specific requirements.