For component or serivce development Servoy has a public api that can be installed with "npm i @servoy/public" for a service or component package. And then needs to be imported in the angular @NgModule declartion:
This will provide various Angular Directives, Filters and Services that a component or service can use to integrate into the servoy product or use it as generic helpers.
For component development the most important one is the ServoyBaseComponent because every component needs to extend that one to get the default interface/behavior for integrating into the NGClient.
Provided Services/Classes
ServoyPlublicService
This service has various function to interact with the Servoy Environment.
classServoyPublicService {/** * get the character for the NumberSymbol that is given like Decimal from the current locale of the client. */publicgetLocaleNumberSymbol(symbol:NumberSymbol):string {returngetLocaleNumberSymbol(this.getLocale(), symbol); }/** * Let the system op the file dialog, this is used by the {@link UploadDirective} */publicshowFileOpenDialog(title:string, multiselect:boolean, acceptFilter:string, url:string):void; public showMessageDialog(dialogTitle: string, dialogMessage: string, styleClass: string, values: string[], buttonsText: string[], inputType: string): Promise<string>;
/** * This created the correct {@link JSEvent} object that is used for handler calls to the server, tries to fill in as much as it can.
*/ public createJSEvent(event: EventLike, eventType: string, contextFilter?: string, contextFilterElement?: unknown): JSEvent;
/** * Returns the current locale string the client is in. */publicgetLocale():string;/** * Returns the full {@link Locale} object of the client. */publicgetLocaleObject():Locale;/** * Internal api, directives can use this to call server side registered services. (this is internal Servoy services).
* Do not try to use this instead of callServiceServerSideApi() - which has to be used for calling server side JS scripting of custom services from packages.
*/publiccallService<T>(serviceName:string, methodName:string, argsObject:unknown, async?:boolean):Promise<T>;/** * Get and listen for i18n message keys, this will call I18NListener.messages() for with an object of key value pairs for all the keys given for the current locale.
* It will also call that same method again if the locale changed in the client with the updated values. * If the caller is destroyed the I18NListener.destroy() must be called to deregister this listener. */publiclistenForI18NMessages(...keys:string[]):I18NListener;/** * Use this to call a script at the server that was given to use by a function spec property. */publicexecuteInlineScript<T>(formname:string, script:string, params:unknown[]):Promise<T>;/** * Services can use this to call there own server side api */publiccallServiceServerSideApi<T>(servicename:string, methodName:string, args:Array<unknown>):Promise<T>;/** * Returns an upload url that can be used to push binary data to the given form/component/property combination. (MediaUpload component)
*/publicgenerateUploadUrl(formname:string, componentName:string, propertyName:string, tus?:boolean):string;/** * Returns an upload url to push binary data to a service serverside function (that gets the file as an argument) */publicgenerateServiceUploadUrl(serviceName:string, apiFunctionName:string, tus?:boolean):string;/** * Use this to get a url to a solutions media for download or src/href */publicgenerateMediaDownloadUrl(media:string):string;/** * returns the ui property value for the given key that is set as a ui property on the application. */publicgetUIProperty(key:string):any;/** * returns the {@link IFormCache} on the client to be able to get some extra data from it like size of that form. */publicgetFormCacheByName(containedForm:string):IFormCache;/** * Services should use this function to push there changed model data to the server (when needed), * so the data is accesable in a servoy solution or stored for a browser refresh. * * @param propertyValue the new value that the service has (and should send to server) for the given propertyName; if you didn't assign it yet to the service's property,
* this method will do it for you. * @param oldPropertValue the value that this property used to have before (or has if you did not change the reference - in this case it should be the same as �propertyValue�);
* this value is used in case of smart types (custom array/custom objects) in order to detect if it's a full change by reference for example
*/ public sendServiceChangeToServer(serviceName: string, propertyName: string, propertyValue: unknown, oldPropertyValue: unknown): void;
/** * show a form popup {@link PopupForm} */publicshowForm(popup:PopupForm):void;/** * cancel/hide the form popup that is currently showing. */publiccancelFormPopup(disableClearPopupFormCallToServer:boolean):void;/** * Returns the value of the testing mode flag (servoy.ngclient.testingMode) from the admin page */publicisInTestingMode():boolean;}
It also has function that exposes the getNativeElement() (the html tag where #element attribute is in). Also getNativeChild() can by overwritten if you have a nested attribute that is more the real element. By default getNativeChild() returns the same thing as getNativeElement()
ServoyApi
The ServoyApi class is the api that interacts with the servoy system (calling the server).
See the api below:
classServoyApi {/** * This should be called by components when they want to show a form, optionally a relationname or formindex can be given.
* It will return a Promise that gives a boolean if the form could be shown (then the component can actually show this form)
*/formWillShow(formname:string, relationname?:string, formIndex?:number):Promise<boolean>;/** * This should be called by components when they it wants to hide a form, optionally a relationname or formindex can be given and
* also the form/relation/index that should be shown when the given form can be hidden so there is only 1 call to hide one form and show another.
* * It will return a Promise that gives a boolean if the form could be hidden (onHide of a form doesn't block the hide)
*/ hideForm(formname: string, relationname?: string, formIndex?: number, formNameThatWillShow?: string, relationnameThatWillBeShown?: string, formIndexThatWillBeShown?: number): Promise<boolean>;
/** * Call to notify the server when this property is gone in edit mode (focus in a field). This can also be configured by using the {@link StartEditDirective}
*/startEdit(propertyName:string):any;/** * This apply is only needed for nested dataproviders, so a dataprovider property of custom type, this will push and apply the data to the data model.
* Normal main spec model dataprovider should be pushed using an Change Emitter. */apply(propertyName:string, value:unknown):any;/** * Call this components serverside api with the given arguments */callServerSideApi(methodName:string, args:Array<unknown>):any;/** * Returns true if the component is currently rendered in the designer (so it can render with some sample data if needed)
*/isInDesigner():boolean;/** * Returns true if this component can trust the html it wants to display (no need to sanatize it). * This can be a client property set on this component itself or more application wide. */trustAsHtml():boolean;/** * Returns true if this component is placed on a css positioned form (not responsive) */isInAbsoluteLayout():boolean;/** * Returns the markupid that this component can use for itself, can be used like this in the template: [id]="servoyApi.getMarkupId()"
*/getMarkupId():string;/** * Returns the formname where this component is part of. */getFormName():string;/** * Internal api, used by {@link ServoyBaseComponent} to register itself to implementors of this ServoyApi object (like form containers)
*/registerComponent(component:ServoyBaseComponent<HTMLElement>):any;/** * Internal api, used by {@link ServoyBaseComponent} to unregister itself to implementors of this ServoyApi object (like form containers)
*/unRegisterComponent(component:ServoyBaseComponent<HTMLElement>):any;/** * Returns the value for the given client property key that was set at the server side on this component. */getClientProperty(key:string):any;}
FormattingService
This is a service that can perform various data -> string formatting or string -> data unformatting on various types, based on the format object that Servoy provides through the format property
/** * format the data give with the {@link Format} object give, optionally using the display or edit format. */public format(data: any, format: Format, useEditFormat: boolean): string /** * utility function to test if a certain key is pressed */public testKeyPressed(event: KeyboardEvent, keyCode: number) /** * utility function to test if only numbers ar pressed. */public testForNumbersOnly(e, keyChar, vElement, vFindMode, vCheckNumbers, vSvyFormat, skipMaxLength)/** * calls the { @link #unformat} function for unformatting/parsing the data given */public parse(data: any, format: Format, useEditFormat: boolean, currentValue?: any, useHeuristics?: boolean): any/** * unformats/parse the give data according to the given format and type */public unformat(data: any, servoyFormat: string, type: string, currentValue?: any, useHeuristics?: boolean): any
MaskFormat
This is a helper class in the formatting area. The formatting service will also use this internally when the format is a configured to be a mask.
import { MaskFormat } from'@servoy/public';this.maskFormat = new MaskFormat(this.format, this._renderer, this.elementRef.nativeElement, this.formattingService, this.doc);
// do call destroy when not used anymorethis.maskFormat.destroy();
LoggerFactory
This service can be used by components and services to create a Logger for a specific class ang log to certain levels.
This is returned by the getLogger() call on the factory. It has the various log functions on the different log levels. Besides that it has a helper method to build a message if that message is a lot of string concatting and should only be build if the message is really logged
this.log =logFactory.getLogger('MyComponent');this.log.error('this is an error');this.log.info(this.log.buildMessage(() =>'a'+ someVariable +' large message'));
/** * Showsthe tooltip on the screen on the position of the mouse event, showing the message with a initial delay and dismissing it after dismissDelay.
*/public showTooltip(event: MouseEvent, message: string, initialDelay: number, dismissDelay: number)/** * hides the tooltip directly that is currently showing. */public hideTooltip()
Provided Directives
svyFormat
This directive takes care of the formatting to the data that is given, it is a ControlValueAccessor in combination of the NgModel It expects that it gets a Format object assigned that a component gets to the format
In the component typescript code:
import { Format, FormatDirective } from'@servoy/public';@Input() format: Format;// you can also get a reference to the directive instance by calling writeValue directly on it.@ViewChild(FormatDirective) svyFormat: FormatDirective;
the tempplate:
[svyFormat]="format"[findmode]="findmode"
It has also a attribute/property by itself "findmode" so the formatter knows when it is findmode and shouldn't try to format at all.
svyStartEdit
This directive calls startEdit on focus through the clientside servoyApi object which a component gets by default and is exposed by the ServoyBaseComponent which all components should extend. The value that it needs is the property where the edit is for, as an example: [svyStartEdit]="'dataProviderID'", so this is the string of the property where it should work on, not the value (see the '' inside the "") and it needs a reference to the actual component through the hostComponent property: [hostComponent]="this"
This directives monitors the key presses to see if the decimal key is press and inserts the correct , or . for the locale the user is in. In expect to get assigned the format so it can check it is a number format.
the template:
[svyDecimalKeyConverter]="format"
svyTooltip
A directive that takes care of the (html) tooltips that must be set on the component, it is a wrapper around the tooltipservice so you don't have to do the event bindings your self.
the template:
[svyTooltip]="toolTipText"
svyTabFix
This directive should be used by components that are showing popups like the typeahead when the component needs to close the popup when the tab key is pressed The component needs to implement IPopupSupportComponent
This directive is a wrapper around ServoyPlublicService.showFileOpenDialog() and ServoyPlublicService.generateUploadUrl() To let the user on click on this component opens a file open dialog and then upload the selected file to the server for the given form and component. Currently the property is hardcoded as 'dataProviderID'. so it will upload to "[formname].[componentname].dataProviderID"
This directive should get as a value the tabSequence property of the component
See Sablotabsequence for more information what a component can do with it (like being a container itself for multiply tabsequences)
Provided Filters
Besides these directives there are also some angular filters:
formatFilter
This is a wrapper around the FormattingService that you can use in labels, so none editable components, instead of using the FormatDirective in components that support edit of data.
After the formatting of the value the trustAsHtml will mark the give value as trusted (if the argument of isTrustedHTML() is true) so then it will not be sanitized or the sanitizer of Angular will sanitize it.
The servoyApi can be asked if it should be trusted (set by the system or a ui property on the component). But it can also be that the component has a property that supports this: