Child pages
  • Specification (.spec file)

Versions Compared

Key

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

...

In this example it has a simple properties like toolTipText (a string) and background (a color) and a dataproviderID property that is of type 'dataprovider' which has an ondatachange that points to the handler onDataChangeMethodID function and the textfield wants to have a callback function called that is called 'onDataChangeCallback'

The field component template html will be expressed like:

Code Block
<svy-textfield name="dataFieldFormatNumber" svy-model="model.dataFieldFormatNumber" svy-api="api.dataFieldFormatNumber" svy-handlers="handlers.dataFieldFormatNumber" svy-apply="handlers.dataFieldFormatNumber.svy_apply" svy-servoyApi="handlers.dataFieldFormatNumber.svy_servoyApi"/>

which is expanded by angular to real html. So every webcomponent gets a number of objects pushed to the instance:

  • model: This has all the properties set in the designer or at runtime (if they are data driven like a dataprovider property), it reflects the model object defined in the spec.
  • handlers: This has all the event functions that are set in the designer like "onclick" or "ondatachange"
  • api: On this object the webcomponents needs to add the api calls that the server can call. Like a requestFocus function.
  • apply: This is a special method that a webcomponent can use to let the server know a property (of the model) is changed. So the value can be applied also on the server (pushed into the record), If a component has fields that uses ng-model then the directive "svy-autoapply" can be used in the html template instead of coding it out in the webcomponent javascript file.
  • servoyApi: This is a component that holds some special servoy api functions to call, currently "setFormVisibility(form,visible,[relation]);

 

So 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 an svy- prefix will result in svyName). The bean module should also include the servoy module so that the bean can use the various servoy directives (starting with svy)

 

Code Block
angular.module('svyTextfield',['servoy']).directive('svyTextfield', 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();
    		 }
    	 },
    	 $scope.api.requestFocus = function() { 
    		  $element[0].focus()
    	 },
    	 $scope.api.getSelectedText = function() { 
    		 var elem = $element[0];
    		 return elem.value.substr(elem.selectionStart, elem.selectionEnd - elem.selectionStart);
    	 }
    	 $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
    };
  })

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:

Code Block
<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.