Child pages
  • Specification (.spec file)

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagejs
titlespec file definition
{
	"name": "packagename-componentname", // String
	"displayName": "more descriptive name that is shown in the designer", // String
	"version": the component version (integer)
	"icon": "A reference to the icon shown in designer" ,
    "preview": "A reference to the preview gif to be displayed" ,

	"definition": "A reference to the js file that implements this component's in the browser",
    "serverscript": "[optional] A reference to the js file that implements this component's server-side logic, if any.",
	"doc": "[optional] A reference to the js file that contains the jsdocs of the component api or model properties.",
    "group": true // default true, so the definition file can be grouped when creating the .war file for deployment
    "deprecated": "This component will be replaced in the next versions.", // (optional) some string to mark the component as deprecated - if it is deprecated
	"replacement": "package-compname",
	"libraries": /* Array of js/css definitions (which are JSON objects with 
          // (optional) in case of deprecation, developer will provide a quick fix for such components to be automatically changed to the given replacement component
                   'name'-the lib name, 'version'-the lib version, 'url'-the lib url,            // (make sure they have compatible .spec defined; in most cases this is useful when moving components from a 'mimetype'-the lib mimetype, one of 'text/javascript' or 'text/css',package to another package or when
                              'group' - give false here when this lib dependency should// notrewriting bea groupedcomponent whenbut exportedkeeping it's contract unchanged)
	"libraries": /* Array of js/css definitions (which are JSON objects with 
              as .war; default true)            'name'-the lib name, 'version'-the lib version, 'url'-the lib url, that
need to be included for this component. */,      "categoryName": "Advanced", // category for form designer palette; only makes sense for components, not services  	"model": {
	    "property1Name": /* type description (optionally including optional default value and others) */,
	    "property2Name": /* type description (optionally including optional default value and others) */
	},

	"handlers": {
	    "handler1Name": { /* handler function type definition*/ },
	    "handler2Name": { /* handler function type definition*/ }
	},

	"api": {
	    "apiFunction1Name": { */ api function signature description json*/ },
	    "apiFunction2Name": { */ api function signature description json*/ }
	},

    "internalApi" : {
	    "internalApiFunction1Name": { */ internal api function signature description json*/ },
	    "internalApiFunction2Name": { */ internal api function signature description json*/ }
    },

	"types": {
	    "customType1Name": {
            "subProp1Name": /* type description" 'mimetype'-the lib mimetype, one of 'text/javascript' or 'text/css', 
                             'group' - give false here when this lib dependency should not be grouped when exported
                             as .war; default true)
                    that need to be included for this component. */,

	"keywords": /* Array of keywords used for searching components in the palette.
				   For instance, for the calendar component some appropriate keywords that might be used are: "day", "month", "year"*/,

           "subProp2Name"categoryName": /* type description" *"Advanced", // category for form designer palette; only makes sense }for components, 	not services

 	"customType2Namemodel": {
        	    "subProp1Nameproperty1Name": /* type description" */,(optionally including optional default value and others) */,
 	    "subProp2Nameproperty2Name": /* type description" */(optionally including optional default value and others) */
	},

   }
}

A ng web component or ng service specifies all its properties in the model section of the .spec file, all the events under handlers section and the api section has the javascript callable api that the webcomponent exposes (that the server/solution can call).

Starting with 8.2 (before these were defined in "api") there is also the internalApi section that is better described in Server Side Scripting page (calls between client and server that are only meant for the code inside the component/service to use).

You can find an example .spec file below.

Library dependency options

The "group" property on the top level spec or in the libraries section tells Servoy if that the definition or library can be grouped or not; by default this is allowed. This is used when a WAR is generated by the WAR Exporter. 

Info
titleThe "group" property

The libraries which contain references to external files cannot be grouped because in the deployed applications the relative paths to those resources are lost, therefore the components will not work.

Such libraries are font-awesome.css or tinymce.js, they should always have "group": false in the specification file of the components that use them.

Deprecation support

A component/service/layout can be marked as deprecated by using the "deprecated" and/or "replacement" properties.

The deprecated components/layouts will not be shown anymore in the palette.

The deprecated services will not be shown anymore under the Solution Explorer plugins node. Markers will be added in case they are used in scripting.

The following combinations are possible:

Code Block
languagejs
"deprecated": "true" // a boolean as a string; this just means "deprecated" without any extra info (it is a string and not a boolean directly in case you want to provide more information about the deprecation; see below)
Code Block
languagejs
"deprecated": "This component will be removed in version X.", // some extra message explaining to the developer why it was deprecated or what to use instead

In the case when the "replacement" property is used (supported for component level deprecation only), the generated markers for the used deprecated components will also have a quick-fix.  

Code Block
languagejs
"deprecated": "This component will be removed in version X.",//some extra message
"replacement": "packagename-compname"

...

Code Block
languagejs
"replacement": "packagename-compname"

...

titleThe "deprecated" property

The "deprecated" property can also be used to deprecate service/component api or properties:

e.g. service function

Code Block
languagejs
"removeKL": {
    "returns": "boolean",
    "deprecated": "Please use removeKeyListener(...) instead.",
    "parameters": [ { "name": "callbackKey", "type": "string" } ]
 }

e.g. component property

Code Block
languagejs
"model": {
    "enabled" : {"type": "boolean", "default": true, "deprecated": "true"},
    ...
}

In this case, the deprecated property will not be shown in the properties view.

Model

...

Apis or handlers are not supported under "model" or "types" because these are just meant as container objects that transmit data/information between the component/service and the server.

For giving types of each property you can use any of the default provided property types that you can find here as well as any custom types defined in the "types" section. Arrays are also allowed (append "[]" to the type name).

Property types under model can be defined in two ways:

simply by specifying it's type: 

Code Block
languagejs
"someTextProperty": "string"

with additional configuration options if you want/need to tell Servoy more about how this property should be treated (this is just a sample, all configuration options are optional and each one will be detailed later); "type" is mandatory.

Code Block
languagejs
"someTextProperty": { "type": "string", "tags": { "scope": "design" },
                                        "values": [ { "Predefined Text 1": "sample text 1" }, { "Predefined Text 2": "sample text 2" } ],
                                        "default": "nothing interesting" }

Array types

To define an array property just append "[]" to the type name.

Code Block
languagejs
"someTextProperties": "string[]"

To specify configuration options for each element of the array you can do:

Code Block
languagejs
"someTextProperties": { "type": "string[]", "elementConfig" : {
                                                "tags": { "scope": "design" },
                                                "values": [ { "Predefined Text 1": "sample text 1" }, { "Predefined Text 2": "sample text 2" } ]	"handlers": {
	    "handler1Name": { /* handler function type definition*/ },
	    "handler2Name": { /* handler function type definition*/ }
	},

	"api": {
	    "apiFunction1Name": { */ api function signature description json*/ },
	    "apiFunction2Name": { */ api function signature description json*/ }
	},

    "internalApi" : {
	    "internalApiFunction1Name": { */ internal api function signature description json*/ },
	    "internalApiFunction2Name": { */ internal api function signature description json*/ }
    },

	"types": {
	    "customType1Name": {
            "subProp1Name": /* type description" */,
            "subProp2Name": /* type description" */
        },
	    "customType2Name": {
            "subProp1Name": /* type description" */,
            "subProp2Name": /* type description" */
       }
    }
}

A ng web component or ng service specifies all its properties in the model section of the .spec file, all the events under handlers section and the api section has the javascript callable api that the webcomponent exposes (that the server/solution can call).

Starting with 8.2 (before these were defined in "api") there is also the internalApi section that is better described in Server Side Scripting page (calls between client and server that are only meant for the code inside the component/service to use).

You can find an example .spec file below.

Grouping of library dependency options

The "group" property on the top level spec or in the libraries section tells Servoy if that the definition or library can be grouped or not; by default this is allowed. This is used when a WAR is generated by the WAR Exporter. 

Info
titleThe "group" property

The libraries which contain references to external files cannot be grouped because in the deployed applications the relative paths to those resources are lost, therefore the components will not work.

Such libraries are font-awesome.css or tinymce.js, they should always have "group": false in the specification file of the components that use them.

Deprecation support

A component/service/layout can be marked as deprecated by using the "deprecated" and/or "replacement" properties.

The deprecated components/layouts will not be shown anymore in the palette.

The deprecated services will not be shown anymore under the Solution Explorer plugins node. Markers will be added in case they are used in scripting.

The following combinations are possible:

Code Block
languagejs
"deprecated": "true" // a boolean as a string; this just means "deprecated" without any extra info (it is a string and not a boolean directly in case you want to provide more information about the deprecation; see below)


Code Block
languagejs
"deprecated": "This component will be removed in version X.", // some extra message explaining to the developer why it was deprecated or what to use instead


In the case when the "replacement" property is used (supported for component level deprecation only), the generated markers for the used deprecated components will also have a quick-fix.  

Code Block
languagejs
"deprecated": "This component will be removed in version X.",//some extra message
"replacement": "packagename-compname"


Using only the "replacement" property will also mark the component as deprecated, and the generated marker will have a quick-fix.

Code Block
languagejs
"replacement": "packagename-compname"


Info
titleThe "deprecated" property

The "deprecated" property can also be used to deprecate service/component api or properties:

e.g. service function

Code Block
languagejs
"removeKL": {
    "returns": "boolean",
    "deprecated": "Please use removeKeyListener(...) instead.",
    "parameters": [ { "name": "callbackKey", "type": "string" } ]
 }


e.g. component property

Code Block
languagejs
"model": {
    "enabled" : {"type": "boolean", "default": true, "deprecated": "true"},
    ...
}

In this case, the deprecated property will not be shown in the properties view.

Model

A ng web component or ng service specifies all its properties and the type of each property in the model section of the .spec file.

Apis or handlers are not supported under "model" or "types" because these are just meant as container objects that transmit data/information between the component/service and the server.

For giving types of each property you can use any of the default provided property types that you can find here as well as any custom types defined in the "types" section. Arrays are also allowed (append "[]" to the type name).

Property types under model can be defined in two ways:

  • simply by specifying it's type: 

    Code Block
    languagejs
    "someTextProperty": "string"


  • with additional configuration options if you want/need to tell Servoy more about how this property should be treated (this is just a sample, all configuration options are optional and each one will be detailed later); "type" is mandatory.

    Code Block
    languagejs
    "someTextProperty": { "type": "string", "tags": { "scope": "design" },
                                            "values": [ { "Predefined Text 1": "sample text 1" }, { "

...

  • Predefined Text 2": "

...

  • sample text 

...

  • 2" } ],
                                            "default": "nothing interesting" }

...

For more information on array types see the array property types page.

Custom types

...


Array types

To define an array property just append "[]" to the type name.


Code Block
languagejs
"someTextProperties": "string[]"

To specify configuration options for each element of the array you can do:

Code Block
languagejs
"someTextProperties": { "type": "string[]", "typeselementConfig" : {
        "someCustomTypeName": {             "name": "string",             "containsForm": "form",             "textstags": { "scope": "tagstring[]design" },
                                                "values": [ { "relationNamePredefined Text 1": "relation",
     sample text 1" }, { "Predefined Text 2": "sample text 2" } ],
      "active": "boolean"         }     }

...

                           "default": "nothing interesting" }
                                            } }

For more information on array types see the array property types page.

Configuration options

There is a set of standard configuration options and each specific property type (for more advanced types like "foundset", "dataprovider", ...) can have some extra configuration options that are detailed by each type.

Stardard tags are the ones that control data synchronization, tags and default/initial/predefined values.

...

Data modifications are automatically propagated from server to client.

For performance (and security) reasons, data modifications from client to server are not propagated by default. To enable this configure pushToServer setting on the property.

...

Custom types

types section defines custom internal types that can then be used by this web component/service for one or more of its properties in the model as well as for parameter and return value types defined in other sections.  (for example a tabpanel component has a "tab" type that describes one tab inside the tab-panel). Custom type definitions each support for defining subproperties whatever is supported under model. For example:

Code Block
languagejs
    "types": {
        "someCustomTypeName": {
            "name": "string",
            "containsForm": "form",
            "texts": "tagstring[]",
            "relationName": "relation",
            "active": "boolean"
        }
    }

For more information on custom property types and how they work see the custom object property types page.

Configuration options

There is a set of standard configuration options and each specific property type (for more advanced types like "foundset", "dataprovider", ...) can have some extra configuration options that are detailed by each type.

Stardard tags are the ones that control data synchronization, tags and default/initial/predefined values.

Data synchronization
Anchor
pushToServer
pushToServer

Data modifications are automatically propagated from server to client.

For performance (and security) reasons, data modifications from client to server are not propagated by default. To enable this configure pushToServer setting on the property.

pushToServer valuedescription
rejectthis is the default, no data synchronization from client to server for this property
allowdata changes from client to server are allowed
shallowsame as allow, but sablo will also add a watch on the model (in the client) and send changes to the server; the watch is based on object reference/primitive value (more performant, but in case of structured/nested objects it will only trigger data synchronization when the objects are different by reference, even if they are actually 'equal' by content)
deep

same as allow, but sablo will also add a watch on the model (in the client) and send changes to the server; the watch is based on object equality (compares old and new values of structured/nested objects, less performant because it keeps and compares two copies of structured/nested objects); "deep" is mostly meant to be used for properties of type 'object' - that  can contain nested JSON - and that for any change (doesn't matter how little) will send over the complete value to the server.

...

Properties can be configured with special tags that may be interpreted by the deployment and/or development environment.

Supported tags are: scope, doc,   addToElementsScope, logWhenOverMax, allowaccess, directEdit, useAsCaptionInDeveloper + captionPriority, showInOutlineView, main and main mode. 


scope: Restricts the model property to: 'design', 'runtime' or 'private'. 

Design means property can only be assigned from designer (not from scripting). Runtime means the property cannot be assigned from designer (will be hidden in Properties View). Private is an internal property, that should only be used by component itself (so component.js or component_server.js). Will not show in Properties View and cannot be assigned from scripting.


doc: a string (can have some basic html tags in it) that describes what the property does to the developer. See Documenting what properties do for more details.


addToElementsScope : boolean

...

If a property should allow the developer to choose in the properties view from a predefined set of values you can use the "values" attribute in combination with "default" and optionally "mode" tag (see above) (default can be one of the predefined values but can also be something else):

...

Similarly to properties of type visible , the properties  of type enabled are also protecting properties, so they can never be modified from the client. 

...

languagejs
titleExample enabled

...

can never be modified from the client. 

Code Block
languagejs
titleExample enabled
"model": {
   "enabled": { "type": "enabled", "blockingOn": false, "default": true }
} 

It is important to use type enabled  if we want the value from the parent container (i.e. form, portal) to be pushed to the component. For instance if a portal is disabled, then all the components from the portal which have a property of type enabled will also be disabled.

Readonly/Findmode
Anchor
ReadonlyFindmode
ReadonlyFindmode

Servoy has 2 special controller/foundset based properties where a component also can be notified for.

controller.readOnly = true in the developer will set this boolean to a property called "readOnly" of a webcomponent, this property should be a runtime or even a hidden property. It should not be a design time property, because the system can set it at any time (to true or false). 

If you want also a design time property to control the editable state then add a second property, see example below, and then having a tag in the template like: ng-readonly="model.readOnly || !model.editable"

Code Block
languagejs
titleListening to readonly
"model": {
  "readOnly": { "type": "protected", "blockingOn": true, "default": false, "tags": {"scope": "runtime"} },
  "editable": { "type": "protected", "blockingOn": false, "default": true }
}

With this property a component can do its thing to set or unset the readonly mode for itself.

It's better to have type this property as "protected" because it should only be able to change at the server, never from the client.

See as an example our bootstrap textbox: https://github.com/Servoy/bootstrapcomponents/tree/master/textbox

findmode is a special type: Findmode property type which can be used to set all kind of other properties which are normally protected from changing on the client side. Or you can just use it as a type for any property you want: 

Code Block
languagejs
titleListening to findmode
"model": {
  "myfindmodeproperty": "findmode"
}

When the find mode changes the boolean value of your property will also change. This way you can react to a form/foundset going into find mode. Like resetting a specific format, allowing any kind of input.

Anchor
documentingProperties
documentingProperties
Documenting what properties do

Documentation for properties can be added to each property's definition via the "tags" section using key "doc" or in the doc file using a variable with same name as the property.

Code Block
languagejs
/**
 * some desciption
 * @example elements.%%elementName%%.yourName = 'myname'
 */
var yourName;

The description that you provide in the .spec file will be used in Servoy Developer as:

  • tooltip in properties view
  • tooltip in solution explorer view
  • tooltip in script editor
  • any other place in developer where it can help the user of your custom component understand what that property does.

For example if you want to document a simple property called "titleText" you can do it like this:

Code Block
languagejs
	(...)
	"model": {
		"titleText": { "type": "string", "tags": { "doc": "The <b>title text</b> is shown in this component's title bar (top side).<br/>Keep it short." } },
	(...)

Basic html tags are supported - similar to the ones supported when documenting methods using JSDoc (in the script editor).

Arrays, custom objects, array elements and subproperties of custom objects can be documented in the same way. For example:

Code Block
	(...)
	"model": {
		"columns": {
			"type": "column[]",
			"tags": { "doc": "Define the table's columns using this property." },
			"elementConfig": {
				"tags": { "doc": "A column definition describes all that is needed to show that column properly in the table." }
			},
			(...)
		},
		(...)
	},
	"types": {
		"column": {
			"dataprovider": { "type": "dataprovider", "forFoundset": "foundset", (...), "tags": { "doc" : "Choose the data that is to be shown in this column." } ),
			"format": { "type": "format", "for": ["valuelist", "dataprovider"], "tags": { "doc" : "This format will be applied on the dataprovider's data before showing it in the table." } },
			"valuelist": { "type": "enabledvaluelist", "blockingOnfor": false"dataprovider", "defaultforFoundset": true"foundset" }
} 

It is important to use type enabled  if we want the value from the parent container (i.e. form, portal) to be pushed to the component. For instance if a portal is disabled, then all the components from the portal which have a property of type enabled will also be disabled.

...

Servoy has 2 special controller/foundset based properties where a component also can be notified for.

controller.readOnly = true in the developer will set this boolean to a property called "readOnly" of a webcomponent, this property should be a runtime or even a hidden property. It should not be a design time property, because the system can set it at any time (to true or false). 

If you want also a design time property to control the editable state then add a second property, see example below, and then having a tag in the template like: ng-readonly="model.readOnly || !model.editable"

Code Block
languagejs
titleListening to readonly
"model": {
  "readOnly": {,
			(...)
		},
	(...)

For information about documenting handlers see Documenting handlers and handler templates below. For information about documenting API functions see the documenting api functions example.

Handlers

The function description in the handlers section can be just "function" or a more complex type describing the arguments and return type:

Code Block
"functionName": {
        "returns":  "string",
        "parameters": [
            { "name": "start", "type": "protectedint" },
        "blockingOn    { "name": true"end", "defaulttype": false "int" } 
        ],
		"tagsprivate": {"scope true // since Servoy 8.3, optional, default is false,
		"ignoreNGBlockDuplicateEvents": "runtime"} },
  "editable": { "type": "protected", "blockingOn": false, "default": true }
}

With this property a component can do its thing to set or unset the readonly mode for itself.

It's better to have type this property as "protected" because it should only be able to change at the server, never from the client.

See as an example our bootstrap textbox: https://github.com/Servoy/bootstrapcomponents/tree/master/textbox

findmode is a special type: Findmode property type which can be used to set all kind of other properties which are normally protected from changing on the client side. Or you can just use it as a type for any property you want: 

Code Block
languagejs
titleListening to findmode
"model": {
  "myfindmodeproperty": "findmode"
}

When the find mode changes the boolean value of your property will also change. This way you can react to a form/foundset going into find mode. Like resetting a specific format, allowing any kind of input.

Handlers

The function description in the handlers section can be just "function" or a more complex type describing the arguments and return type

Code Block
"functionName": {true // since Servoy 2020.12, default is false
}

The "private" configuration makes the handler only accessible from Server Side Scripting, not from the client/browser itself.
The "ignoreNGBlockDuplicateEvents" configuration makes the handler ignore the system NG_BLOCK_DUPLICATE_EVENTS property.

A handler can have a JSEvent property type which is able to map a Dom event to a JSEvent object that the handler can have in Servoy scripting. A mapping is mostly made automatically by calling using in the template: 


Code Block
svy-click='handlers.onActionMethodID($event)'

If you need to make one manually you can also do that by using the $utils factory service


Code Block
$utils.createJSEvent(e,"onselectionchanged")


Anchor
documentingHandlers
documentingHandlers
Documenting handlers and handler templates

Handlers can be documented - for use inside the developer - using the following keys (these are used in properties view tooltip or when generating new handler methods):

  • doc (used to be description; describes when the handler will be called and what it's for)
  • code (when a new method  is created for that handler, this default code template will be inserted)
  • for return value details returns can be an object with sub-keys: { type, doc, default (only relevant if "code" was not given) }
  • for parameter details parameters: [ { doc, optional (is false by default) } ].

For example:

Code Block
languagejs
"onDataChange": {
        "returns":  { "type": "boolean", "doc": "if it returns true then the data change is considered to be valid, otherwise it will be blocked/reverted by the component", "default": true },
        "parameters": [
            { "returnsname": "newValue", "type": "string", "doc": "the new value entered by the  "parametersuser": [},
            { "name": "startoldValue", "type": "int" },
  "string", "optional": true, "doc": "the previous value if available" } 
        {],
"name": "end", "type": "int" } 
        ]		"doc": "<b>onDataChange</b> will be called if the user modified the field's content and then either tabbed out/clicked outside of the field or hit enter. The handler can decide wether to allow the change or not.",
		"privatecode":true "// since Servoy 8.3, optional, default is false
}

...

 if we set this we should remove the 'default' from 'returns'\nreturn !!newValue;"
}

For information about documenting properties see Documenting what properties do above,. For information about documenting API functions see the documenting api functions example.

Api

This section defines the signatures and behaviors of functions that can be called from the solution on this component/service.

...

The implementation of such api functions can be located either in the browser-side component/service logic implementation ("definition" in .spec file) or in the server-side component/service logic implementation ("serverscript" in .spec file)

There are several types of of sync/async api calls described below.

Anchor
HiddenDivNote
HiddenDivNote

Note
titleAbout calling browser-side api functions of components


When a component (not service) sync or simple async api function (see below) that the solution can call is implemented in browser-side component/service logic implementation ("definition" in .spec file), it is important to note that calling such a function when the form of that component is not shown already created in browser DOM will result in a temporary "force-load" of that form in a hidden div in the browser - just to be able to call that api function. As this is usually not useful and will slow-down the solution due to the hidden loading of a form, this situation should be avoided (either by the solution - calling the api call later after the form was shown - or, where possible, by using delay until form loads async api functions)by using delay until form loads async api functions in components - see below).

Servoy will log warning messages each time a sync API call to browser executes when the browser doesn't have the needed form present in DOM yet (triggering a force-load of the form in a hidden div). Most of the times this happens when solutions call component sync api functions to browser inside the onShow handler of a form.

For information about documenting API functions see the documenting api functions example.

Sync functions

This is the default type of api function; the example above is a sync api function definition. Sync functions will call the client and wait for the api function to execute/return before continuing. Sync api functions can have a return valueof api function; the example above is a sync api function definition. Sync functions will call the client and wait for the api function to execute/return before continuing. Sync api functions can have a return value.

Client side code of the sync api function can return either directly the intended return value or a Promise that in the end resolves with the intended return value. Server will wait for any client returned Promise to resolve before resuming server-side code execution.

In case of component sync functions, if the form is not present in browser's DOM then sync calls will force-load it in a hidden div just in order to execute the sync function on the component.

Sync functions that do not block event processing

...

Just add "async": true (another optional parameter (that by default is false)) to the call definition; it means the client side api is not called right away, but at next message sent to the clientsent to the client.

In case of component async functions, if the form is not present in browser's DOM when the async call is supposed to execute (later) then it will force-load it in a hidden div just in order to execute the async function on the component.

Code Block
languagejs
        "executeSomethingLater": 
        {
            "async": true
        }

...

They are useful when for example you want to send progress information to the service client-side while executing a long-running-operation server-side.

Async-now function calls will not send other pending async calls to client nor update the client's state with other pending changes (model updates of components/services/etc.).

Just add "async-now": true (another optional parameter (that by default is false)) to the call definition.

...

Just add "discardPreviouslyQueuedSimilarCalls": true (another optional parameter (that by default is false)) to the call definition. This flag was also known previously as "globalExclusive" (but that is now deprecated).

Code Block
languagejs
languagejs
        "requestFocus": {
            "parameters": [ { "name": "mustExecuteOnFocusGainedMethod", "type": "boolean", "optional": true }],
            "requestFocusdelayUntilFormLoads": {true,
            "parametersdiscardPreviouslyQueuedSimilarCalls": [ { "name": "mustExecuteOnFocusGainedMethod", "type": "boolean", "optional": true }],
            "delayUntilFormLoads": true,
            "discardPreviouslyQueuedSimilarCalls": true
        }

...

true
        }

Allow server side calls when component or parent form is not visible

By default, server side calls coming from client are ignored if the component or the parent form is not visible (anymore). For example, a call to a server side function when switching to a new form, to do some cleanup, might get blocked. To still allow these calls, you should add "allowaccess" : "visible" to the function definition in the .spec file.

Server Side Scripting

A component or service can have a server-side part as well (optional); this logic is executed directly on the server; in the spec file this is configured like:

Code Block
languagejs
title.spec file
"serverscript": "servoydefault/tabpanel/tabpanel_server.js",

See Server Side Scripting for more info about server side scripting.

Doc file

(From 2021.12 on)

A component or service can have a server-side part as well (optional); this logic is executed directly on the server; in the spec file this is configured like:doc file for specifying documentation of the api and model properties. This is the same as the JSDoc in client side (.js) file, but is needed because NG2 doesn't have a js file that we can use in this way, requiring doc to be specified in another place.

The api doc/property doc can also be specified in the spec file itself using the doc property , however this is suitable only for small descriptions.  

Code Block
languagejs
title.spec file
"serverscriptdoc": "servoydefault/tabpanel/tabpanel_serverdoc.js",

...


Code Block
languagejs
titletabpanel_doc.js file
/**
 * some sample text
 * @example elements.%%elementName%%.yourName = 'myname'
 */
var yourName;

/**
 * This is a sample function from doc javascript file.
 */
function somemethod() {
}

Palette categories

Web Components are organized in component packages. The palette of the WYSIWYG editor shows components grouped by package name. To further group components from the same package, the property 'categoryName' can be used. 'categoryName' is a property that each component can specify in its spec file. The palette then displays components belonging to the same category grouped under the specified 'categoryName'.

...

Code Block
languagejs
titleCategory Name
linenumberstrue
{
	"name": "packagename-componentname",
	"displayName": "String more descriptive name that is shown in the designer",
	"categoryName": "Advanced",
...
}



...


Example
Anchor
example
example

...