Versions Compared

Key

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

...

Here is an example of such a .js file:

 

Code Block
angular.module('servoydefaultTextfield',['servoy']).directive('servoydefaultTextfield', function() {  
    return {
      restrict: 'E',
      transclude: true,
      scope: {
        model: "=svyModel",
        api: "=svyApi",
        handlers: "=svyHandlers",
        svyServoyapi: "=" // only needed if you really need access to this servoy provided API
      },
      controller: function($scope, $element, $attrs) {
    	 // fill in the api defined in the spec file
    	 $scope.api.onDataChangeCallback = function(event, returnval) {
    		 if(!returnval) {
    			 $element[0].focus();
    		 }
    	 },
		 /**
		  * Set the focus on the textfield.
		  */
    	 $scope.api.requestFocus = function() { 
    		  $element[0].focus()
    	 },
 
		 /**
	      * Get the selected text.
		  * @return {string} the text selected in the field.
		  */
    	 $scope.api.getSelectedText = function() { 
    		 var elem = $element[0];
    		 return elem.value.substr(elem.selectionStart, elem.selectionEnd - elem.selectionStart);
    	 }
		
          /**
			* Set the selected text.
			* @param {int} start the start index in the text
			* @param {int} end the end index in the text
			*/
    	 $scope.api.setSelection = function(start, end) { 
    		 var elem = $element[0];
    		 if (elem.createTextRange) {
    		      var selRange = elem.createTextRange();
    		      selRange.collapse(true);
    		      selRange.moveStart('character', start);
    		      selRange.moveEnd('character', end);
    		      selRange.select();
    		      elem.focus();
    		 } else if (elem.setSelectionRange) {
    		    	elem.focus();
    		    	elem.setSelectionRange(start, end);
    		 } else if (typeof elem.selectionStart != 'undefined') {
    		    	elem.selectionStart = start;
    		    	elem.selectionEnd = end;
    		    	elem.focus();
    		 } 
    	 }
      },
      templateUrl: 'servoydefault/datatextfield/datatextfield.html',
      replace: true
    };
  })

It is a good practice to document your components, please note the jsdoc tags in the code above.

 

First you can see that the directive declares declaring that it uses a few things that Servoy makes available to itprovides:

  • svyModel: this is the object that contains all properties that the .spec file declares in it's "model" section.
  • svyApi: this is the object that the web component .js file must populate with all the client-side API functions that the .spec file declares in it's "api" section. Some apis can also be implemented in serverside scripting, see "Serverside scripting" section of the Specification page.
  • svyHandlers: this is the object that contains all handlers that the .spec file declares in it's "handlers" section. It is pre-populated by Servoy, so the handlers are already there, ready to be used.
  • svyServoyapi: this is an API that Servoy provides to the component - if the component needs to do manual 'apply' or other operations. See the servoyApi section below.

...

A handler call (handlers.x()) to the server returns a promise (http://docs.angularjs.org/api/ng.$q) to which the webcomponent web component can register a callback - so that an event/handler that executes on the server can return a value to the web component's call.

Info
titleNote about directive/WebComponent received attributes

A WebComponent directive should expect that the attributes it receives (except for svyApi) can completely change.

For example when the record shown by a component changes the svyModel gets changed by reference. So be careful about caching model contents and accessing some model content only in the link method of the directive for example (which will not be called again when only the displayed record changes).

If you write any repeater components (such as custom portals/table views/list views) you should make sure you don't change the svyApi that you give to the same child WebComponent directive (and which was populated by that directive initially) when the record that it displays changes.

...

ServoyApi
Anchor
servoyApi
servoyApi

...

Method

Parameters

Description

apply

Anchor
apply
apply

propertyName

the name of the property of type dataprovider

Pushes a changed dataprovider value of the component to the server (sets it in the actual record). So this is the only way to acutally make the server's data aware of browser-side changes to 'dataprovider' typed properties.

It is used internally by the svy-autoapply directive, but it can also be called directly by the web component itself.

For example the radio button manually pushes the new value to the server when the radio is clicked (without using svy-autoapply):

Code Block
languagejs
titleradio.js
$scope.radioClicked = function()
{
	$scope.model.dataProviderID = $scope.model.valuelistID[0].realValue;
	$scope.svyServoyapi.apply('dataProviderID')
}
Info
titleIMPORTANT
In order to be able to change server-side dataprovider values using apply, the .spec file must declare that dataprovider property from the model as pushToServer: allow or higher. Otherwise the server will reject the dataprovider value updates and log a change denied warning.

callServerSideApi

methodName

the name of the serverside method to call

args

the arguments of the serverside method

Used on the client side to call a function which is defined in the server side api of the component.

It returns a promise of angular where the then function will give you the return value of the callback.

Code Block
languagejs
titlecomponent_server.js
$scope.mycallback = function(name,type) 
{
    return "something";
}

In the controller or link function of the component, "mycallback" can be invoked via

callServerSideApi:

Code Block
languagejs
titlecomponent.js
 $scope.servoyApi.callServerSideApi("mycallback",["string",1])
.then(function(retValue) {
   console.log(retValue);   
 });

formWillShow

formname

– the name of the form which will be shown

relationname

– the name of the relation (optional)

formIndex

– the formIndex in the tabpanel (optional)

Prepare the form for showing. Example switching tabs in the tabpanel component:

Code Block
languagejs
titletabpanel.js
function setFormVisible(tab,event) 
{
	if (tab.containsFormId) $scope.svyServoyapi.formWillShow(tab.containsFormId,
       tab.relationName);

hideForm

formname

– the name of the form to hide

relationname

the name of the relation (optional)

formIndex

the formIndex in the tabpanel (optional)

Hides the form. The outcome of the returned angular promise is a boolean, which is true if the form was hidden.

Used by the tabpanel to hide the previously selected tab.

Code Block
languagejs
titletabpanel.js
$scope.select = function(tab) 
{
    if (tab && tab.containedForm && !tab.active)
    {
		//first hide the previous form
		var promise =  $scope.svyServoyapi.hideForm( 
			$scope.model.tabs[$scope.model.tabIndex -1]);
		promise.then(function(ok) 
		{
			$scope.model.tabIndex = getTabIndex(tab)+1;
			//show the selected form
			$scope.svyServoyapi.formWillShow(			   
            tab.containedForm, tab.relationName);
    	    tab.active = true;
		})    		  
   	}	  
}

getFormUrl

formName

Return the URL of a form. It can be used together with ng-include to include a

form in the component template:

Code Block
languagexml
titlecomponent.html
<div ng-include="svyServoyapi.getFormUrl(myFormName)" ></div>

startEdit

Anchor
startEdit
startEdit

propertyName

the name of the property which is edited

Signal that the editing of a property has started, usually at focus gained.

It is automatically used internally by the svy-autoapply directive.

In case svy-autoapply is not used, startEdit can be called manually by the component itself to notify the server that the record should go into edit mode (by giving the name of the model 'dataprovider' typed property):

Code Block
languagexml
titlecomponent.html
 <input ng-focus="svyServoyApi.startEdit('dataproviderID')"/>