Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 16 Next »

The javascript file of the bean component can put those into its scope, every webcomponent is a angular module of its own, with at least 1 directive that is describing the component itself. So the module and the one directive should be named like the bean (camel case notation so a servoydefault- prefix will result in servoydefaultName). The bean module should also include the servoy module so that the bean can use the various servoy directives (starting with svy)

 

angular.module('servoydefaultTextfield',['servoy']).directive('servoydefaultTextfield', function() {  
    return {
      restrict: 'E',
      transclude: true,
      scope: {
        model: "=svyModel",
        api: "=svyApi"
      },
      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.

The model and api objects are stored in its own scope and then inside the controller function the various api calls are implemented besides the onDataChangeCallback function used as a callback of the ondatachange for a dataprovider.

The template then looks like this:

<input type="text" style="width:100%; height:100%; background-color:{{model.background}};"
   ng-model="model.dataProviderID" title="{{model.toolTipText}}"
    svy-autoapply  svy-format="model.format"/>

Where the various properties are then taken from the model for specific html tags.

A handler call to the server does get a promise back (http://docs.angularjs.org/api/ng.$q) where the webcomponent could register a callback on so that an event that executes on the server can return a value to the webcomponents call.

Note 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 it gets will change 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

The servoyApi is a Servoy specific api which can be used by web components to interact with the server. It must be declared in the private scope of the component.

 

component.js
angular.module('mypackageComponent',['servoy']).directive('mypackageComponent', function() {  
    return {
      restrict: 'E',
      scope: {
    	  model: "=svyModel",
          svyServoyapi: "="
      },

 

The servoyApi provides the following methods:

 

Method

Parameters

Description

apply

propertyName

the name of the property of type dataprovider

Pushes a changed dataprovider value of the component to the server.

It is used by the svy-autoapply directive, but it can also be used directly by the webcomponent.

For example the radio button pushes the new value to the server when the radio is clicked:

radio.js
$scope.radioClicked = function()
{
	$scope.model.dataProviderID = $scope.model.valuelistID[0].realValue;
	$scope.svyServoyapi.apply('dataProviderID')
}

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.

component_server.js
$scope.mycallback = function(name,type) 
{
    return "something";
}

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

callServerSideApi:

component.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:

tabpanel.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.

tabpanel.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:

component.html
<div ng-include="svyServoyapi.getFormUrl(myFormName)" ></div>

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 by the svy-autoapply directive.

In case svy-autoapply is not used, startEdit can be called to notify the server that

the record should go into edit mode, like (giving the name of the model property):

component.html
 <input ng-focus="svyServoyApi.startEdit('dataproviderID')"/>
  • No labels