CodeCoupler UI Component
The Component class is the base class of all CodeCoupler components. All the following
functionalities and rules affect all components.
Each component will have the following members:
Component Construction
prepare()andfinalize()-
These method names are used internally and should not be used. Otherwise the component will not work properly.
init():-
All components use this method name for custom initialization code. It will always used when a component is created.
boot()andstart():-
These method names is only used for the initialization process of some components.
initialized-
The property
this.initializedreturn a promise which will be resolved if the component ist initialized or rejected if an error occurs while initializing.This can be used for example in the
initmethods to define actions that will be executed after the initialization phase ends. You need to know that after the init method, additional steps may be carried out. In some cases it makes sense to wait for this first:
Common Getters
env-
Prepared environment and options variables.
id-
With
this.idyou can read the id of the current component. settings-
Access the system wide settings. Details explained in "System Wide Settings".
options,constructor.defaults-
Over the property
this.optionsthe component get access to the options the user have defined in the start definition object for your component.The options will be merged with the static property
defaultsof the component class and all static propertiesdefaultsof all prototypes of the component.With this mechanism you can define the default values for all options and the user can set default values for each new instance.
If you set a new value to
this.optionsit will be merged to the already existing ones!
Destroying
asyc destroy(),destroying,Event destroyed-
Method to destroy the component. The base method will call all
destroymethods of all child components. The function can be called multiple times, but is only executed once. To get the status if destroying is running, test if the propertythis.destroyingreturnstrue.At the end of the destroying process the component will trigger the event
destroyed. As argument the event will have the component instance.The method blocks the component with the message from the system wide setting
messages.COMMON.DESTROYINGwhile executing. On finish the component will be blocked with the messagemessages.COMMON.DESTROYEDwith a special overlay styledestroyedwhich is black and non-transparent. The method do not wait while the last blocking is ready.The method can be overriden to add own functionality. In this case the super method should be called. You should ensure that no error will be thrown:
Widget Handling
widget(widgetStart)-
Widget factory method to initialize an new widget instance.
Application Handling
app(appStart)-
Application factory method to initialize an new application instance.
apps-
With
this.appsyou can access an object of all applications of this component. The id of the application is used as property name.You get only running apps. If the id is not in this object the application was closed. This can be done by a user or programmatically. This is important to check because the application instance can continue to exist, even the application was closed.
frontedApp-
Returns the instance of the fronted application. Can be null if component do not have an application started.
Event Management
on(event,handler),one(event,handler),off([event],[handler]),trigger(event,argments)-
Each component provide methods to bind and trigger functions based on event names.
on: Add a handler to an event.one: Add a handler to an event that will be executed only one time.off: Remove a handler to an event. Ifhandleris omitted all, handler to this event will be removed. Ifeventandhandlerare omitted, all handler for all events will be removed.trigger: Trigger an event.
Hints
hint(text),hint(type, text),hint(type, text, element),$hintContainer-
Show an hint with the given style in
type. Depending on which component this method is used, the hint is displayed in the following places:Component Hint Target System In the current stage Stage In the stage element Application In the content area of the application Widget In the widget element The argument
typespecifies the hint style. Predefined areinfo,successanderror. If ommitedsuccesswill be taken. You can add or modify these styles in the system wide settinghints. Each property in this object represents one style. A style is a configuration object which will start a jPanel hint extension.The signature including
elementis used internally. If you need to specify a custom element in which the hint should be displayed, you can use `element which can be defined as HTMLElement, jQuery object or selector string.The getter
$hintContaineris used internally. Do not override.
Visibility
visibility,$visibility,static visibilityValues,static $visibilityValues(value),Event visibility-
With
this.visibilityyou get one of the value from the static objectComponent.visibilityValues:Component.visibilityValues.HIDDENComponent.visibilityValues.VISIBLEComponent.visibilityValues.PARTLY
A component can set its visibility status with
this.visibilityto one of these values. But as soon as you ask for the value, it does not mean that exactly the same will be returned.If you ask for the value, further conditions are checked to determine whether a component is visible or not. A component is not visible for example if it is inside of an application panel that is minimized. Or it is also not visible if it is in an application panel behind another maximized panel. This is not only checked for the panel above, but also for the entire route down to the system.
The value
PARTLYwill returned if a component is in a panel behind other panel which are normalized. This means that the component can be partially visible or completely covered by other panels. This cannot be determined more precisely.It is very important if you implement widgets which hold itself other widgets to maintain the visibility status of these widgets. For example if you implement a tabed display of multiple widgets, you should set the visibility of each one, depending on which tab is displayed.
Whenever the visibility of a component is supposedly changed, the event
visibilityis triggered. The eventvisibilitywill be triggered often without checking if the visibility have really changed. This is becuase the calculation of the visibility is much more intensive and is not used everytime. You can bind a callback to this event, check withthis.visibilityand get the new or old status.The static function
$visibilityValues(value)is just a helper which converts a visibility value to its name.The getter
this.$visibilityreturns the value that have been set for the component, not the calculated.
Resizing
Event resize-
Whenever the resize event is triggered in a component, the component will trigger this event on all child components. An application will trigger this event if the panel is resized, normalized or maximaized. If you implement a component wich change its size you should trigger this event one time in your component. If you change sizes of child components you should trigger this event in the affected components one time.
Blocking
► Read more about blocking components
Blocking Methods
async block({type, text, handle, settings, sticky})-
Block the the component with a message. Keep in mind that this is an async method. This is because the blocking layer will fade in and the method will resolve if the fading is finished.
Different signatures are available for this method:
block()block(text):block(text, {...})block(handle, {...})block(handle, text)block(type, text)block(type, text, {...})
type: String-
If you set
typetoinfoorerrora different stylesheet will be used. If you do not specifytype,infowill be used as default.Styles will be configured in the system wide settings in the property
block.Will not used if
handleis given. text: String | HTMLElement | jQuery Object-
messagecan be a simple string with HTML elements, an HTMLElement or a jQuery object which will be displayed.If you set
messageto an empty string,null, orundefinedthe method produce an empty container which have the fill width and height of the component. This can be used to display just an empty blocking layer or to add or modify the content as you like over the return valuecontainer. handle: String-
Use
handleto call theblockmethod again and update an existing blocking layer. Must be created withnew BlockHandle()or read from the return value of previousblockcalls. settings: Object-
Here you can override the system wide settings of
blockfor only this blocking call.Will not used if
handleis given. sticky: Boolean-
Create a "sticky" blocking layer if
true. Please read the section about the "stacking concept" above for more details.
async unblock(handle)-
Unblock the component. Keep in mind that this is an async method. This is because the blocking layer will fade out and the method will resolve if the fading is finished.
handle: String-
The handle returned from the
blockmethod have to be used here to unblock a specific blocking layer.
async block({..., element})andasync unblock(handle, element)-
The methods
blockandunblockhave one more signature with which you can specify an element to block instead the current component.Normally you cannot set what HTMLElement should be blocked. This will be set by the component. The only case you could use this property is calling the methods from the super instance with type of
Component. Theelementcan be defined as HTMLElement, jQuery object or selector string.
Blocking Getter
blocked-
Returns
falseif component is not blocked or one of the stringsinfoorerrordepending on the block type. $blockContainerand$blockArguments-
Used internally. Do not change.
Preloading Assets
With the method preload you can preload assets. The default progress behaviour is to block the
component and show the progress in percent.
Important: Do not use the preload functions in the init method of an application. Because at
this time the application do not have a panel and the default progress handler will try to block the
application. This leads to an exception.
Preloading Methods
async preload(config,[args],[settings])-
To start a loading process you have to call the method
async preload()with a configuration object.config: Object-
Each property of this configuration object have to be a name of a preloading handler. It's value will be used as argument for the specific handler. The returned promise of the method will resolve if all assets are loaded or reject if an error occurs.
The default preloading handlers are
dataSources,fontsandfontsRequired. Custom handlers can be added. args: Any-
Specify here whatever you want, that will be passed on to the progress callbacks (see below).
settings: Object-
Specify an object with some options. Default values will be taken from
settings.preloaderof the system instance. The object can have the following properties:delay: Object-
Specify a delay for debuging purposes. The object have the following properties:
enabled: Boolean.-
If
truedelaying will be enabled. minMSec: Integer.-
The minimal time in milliseconds that will use each asset for loading.
maxMSec: Integer.-
The maximal time in milliseconds that will be added to the minimal time above. It will be used a random time between minimal and maximal delay on each asset loading.
progress: Class-
Progress handler which will be instatiated for each
preloadcall. The methods get notified for each progress update and can use this information to present them to the user. Read below for more informations.
registerPreloader(name,func)-
Method to register a new preloading handler.
name: String-
The the property name of the configuration object that will be used for this handler.
func(assets, progress, delay)-
Callback function of the custom handler.
assets: Any-
The configuration value for this handler.
progress: Object-
The object have three properties that have to be updated by the handler during the loading process.
total: Number-
The handler have to count the assets given in the argument
assetsas soon as possible and update the number here. success: Number-
Whenever an asset is loaded you have to increase the number here.
failed: Number-
Whenever an asset cannot be loaded you have to increase the number here.
delay: Object-
Whenever possible implement a delay according to the
delayargument (details are explained above).
Progress Handler Class
The start have to provide the following methods:
async start(component,args)-
Callback that will be called when the preload processes starts.
component: Component-
The current component instance that initiated the preload process.
args: Any-
The value that have been used starting the preload process.
async update(component,progress,args)-
Callback that Will be called everytime the progress summary of the loading process have changed. Everytime a handler will change its progress object, the component will calculate a summary of all loading assets.
component: Component-
The current component instance that initiated the preload process.
progress: Object-
An object with the following properties:
total: Number-
Total Assets that have to be loaded.
success: Number-
Number of succesful loaded assets.
failed: Number-
Number of assets that failed loading.
percent: Number-
Percent of assets that sucesful loaded or failed.
args: Any-
The value that have been used starting the preload process.
async end(component)-
Callback that will be called when all preload processes finished and all calls to the
updatemethods have been completed.component: Component-
The current component instance that initiated the preload process.
Default Preloading Handlers
dataSources: Object[]-
The value of
dataSourcesmust be an array of objects. The objects have to be the arguments used in thecomponent.dataSource()method. fontsandfontsRequired: string[] | object-
The value of
fontsandfontsRequiredcan be an array offont-facenames to load. The difference betweenfontsandfontsRequiredis that the promise will rejected if loading fails infontsRequiredand will always resolve infonts.In addition to the name, the variation can also be specified. Herefore the
Font Variation Descriptionwill be used like explained here: [https://github.com/typekit/fvd]Example: "Font Awesome 5 Free:n4,n9" will load the font
Font Awesome 5 Freein normal style and with the weights 400 and 900.Because the external library Web Font Loader is used under the hood, you can alternatively set the configuration object directly.
Data Handling
Datasource Factory
dataSource(),dataSources-
Create and retrieve datasources created by this component. With
this.dataSourcesyou can access an object of all datasources of this component. The id of the datasource is used as property name.
Handling Data Changes
Each component have some prepared methods to handle pending data changes in datasources. Whenever a
data item of a datasource have been modified, created or deleted the datasource is marked as dirty
and this means that pending data changes exists.
Each component handle self-created datasources and all datasources of all child components.
In many cases a component receive a datasource instance as option. In this case all the data
handling will not work as expected. For this case you can and should link the datasources with
dataSourceLink(). All data handling methods will take linked datasources also into account.
dataSourceLink(dataSource): Void-
Link an existing datasource which was not created by the component itself and was passed via an option from a parent component.
All linked datasources will be handled from all other data handling methods as they would be self-created.
hasChanges(commited): Boolean | Null-
Checks if any own datasource or any datasource of any child component have pending changes.
Returns
trueif pending changes exists,falseif no pending changes exists andnullif the method cannot decide if pending changes exists.The last case, returning
nulloccurs if a component cannot commit its current input values. To check this before checking the datasourcesthis.commitChanges()will be called. If this method returnsfalsethe methodhasChangesreturnsnull.If you want to add more checks in your component, override this method. You should call firstly the
super.hasChanges()method and interrupt if changes already detected: commitChanges(blured): Boolean-
Perform any needed actions to take over currently entered values in input fields or other editor elements and save them in data items of datasources.
The method can return
trueif the commit has succeeded andfalseotherwise. This can occur for example if an input field have an invalid value.The base method just calls
document.activeElement.blur()if the browser supports this. This is done so that the focus is removed from the current input field and the entered data may also change a datasource.After this the method calls the
commitChangesmethod of any child component. All method of all components will be called regardless of their return values. If any of these methods returnsfalsethe method will return alsofalse.If you want to add more actions in your component, override this method. You should override this method especially if your component use input elements. In case the
commitChangesis called you should perform a validation of all input fields. If a validation fails you should returnfalse. Do not show the error messages at this time. Wait for callingtoggleErrors(true).If the validation succeed you should persist your values into the datasource.
In your override you should call firstly the
super.commitChangesmethod and merge its return value with yours: async refreshData(): void-
Calls the
readmethod of any own datasource or any datasource of any child component. The method will fetch all data from the remote server.You have to pay attention, because this method will discard all local modifications.
The method try to call all
readmethods in each component in parallel.If you want to add more actions in your component, override this method. You should call firstly
await super.refreshData(): cancelChanges(): void-
Calls the
cancelChangesmethod of any own datasource or any datasource of any child component. The method will reset all data items to the values fetched from the remote server.You have to pay attention, because this method will discard all local modifications.
If you want to add more actions in your component, override this method. You should call firstly the
super.cancelChangesmethod: async saveData(commited): void-
Calls the
syncmethod of any own datasource or any datasource of any child component. The method will send all modified data to the remote server.Before all checks
this.commitChanges()will be called. If this method returnsfalsean exception will be thrown. For now a simple Error object will be thrown with the messageCommit not possible. In future versions this may change.You can avoid commiting changes by setting the argument
commitedtotrue. You should check in this case the return value ofthis.commitChanges()or betterthis.hasChanges()before callingsaveData(true).The method try to call all
syncmethods in each component in parallel.If you want to add more actions in your component, override this method. You should call firstly
await super.refreshData(): toggleErrors(mode): void-
Set the error mode in component and in any child component.
modeshould be a boolean value.The idea behind this is to controll of how the input validation errors should be shown. You do not have to follow these pattern:
- The component start with the status of not showing any errors.
- The user start to enter values in an input field. Either the field prevent an input of an invalid value or show a subtle note like a red border.
- The user try to save although validation errors exists.
- The parent logic detects validation errors with
hasChangesorcommitChangesand callstoggleErrors(true). - Now the component should show detailed validation error messages.
- The user correct the values and save again.
- The parent logic do not detect any validation errors, the sync of all datasources
succeed and calls
toggleErrors(false). - From now on no detailed error messages will be shown and anything starts from beginning.
The method
saveDataUIimplements this pattern.You should override this method especially if your component use input elements. You should call firstly
super.toggleErrors()and remember the current status:
Data Handling UI Methods
In addition to the previous data handling methods exists some data handling methods with UI elements and user interactions. They cover the most use cases in which the data handling methods will be used in combination with UI elements:
refreshDataUI()-
Will check pending data changes with
this.hasChanges()and callthis.refreshData()if no changes detected. Returnstrueon success, otherwisefalse.If they are pending changes the user will be asked if he want to discard all changes before calling
this.refreshData(). The confirm messages will be taken frommessages.DATA.CONFIRM_REFRESHAfter refreshing an error or success hint will be shown. The messages of the hints will be taken from the system wide settings
messages.DATA.SUCCESSandmessages.DATA.ERROR. An error will be loged in the console. cancelChangesUI()-
Will check pending data changes with
this.hasChanges()and callthis.cancelChanges()if no changes detected. Returnstrueon success, otherwisefalse.If they are pending changes the user will be asked if he want to discard all changes before calling
this.cancelData(). The confirm messages will be taken frommessages.DATA.CONFIRM_CANCEL saveDataUI(consoleError)-
Will check pending data changes with
this.hasChanges()and callthis.saveData()if changes detected. Returnstrueon success, otherwisefalse.If they are no changes just a hint will be shown. The messages of the hints will be taken from the system wide settings
messages.DATA.NO_CHANGES. In this case the method returnstrue.If validation errors exists and
hasChangesreturnsnulla hint will be shown andsaveDatawill not be called. Insteadthis.toggleError(true)will be called.After synchronizing the datasources an error or success hint will be shown. The messages of the hints will be taken from the system wide settings
messages.DATA.SUCCESSandmessages.DATA.ERROR. An error will be loged in the console if you set the argumentconsoleErrortotrue.If no error occurs
app.toggleErrors(false)will be called.
Manifest
A component can provide a static field manifest which contains properties of how the component
should be presented and other descriptive informations. This is used for example for displaying an
application component in titles, launching buttons or other UI elements. Because these informations
are needed before the application is created it is a static property.
Because a developer maybe do not specify all properties in its component you cannot just read the
static property manifest to get all informations. You have to use the static method
Component.$manifest(component) which will merge the values of all static properties of all parent
classes.
name[ String ] (Default: Taken from base class)-
The name of the application.
iconHtml[ String ] (Default: Taken from base class)-
The html element should inherit the font-size. If you use FontAwesome, you should always add the
fa-fwclass. level[ String ]-
In which stage level this componenet will be loaded if not otherwise specified.