Utilizing External Libraries
You are able to make use of External libraries when building your own UI Components. This can be achieved by either specifying an external library on your Component using the Component External Library Documents
field, or at a lower level using a Lazy Loading
technique within your event functions (eg. a Component's Load
Function). In either case, the external library needs to be installed on the Formbird platform before it can be accessed.
Installing Custom Component Modules
Please contact your Formbird administrator to request / perform this setup in your environment.
- Download the required module from your chosen code repository.
- Copy the module to a new folder under the
./server/public/vendor/custom-component-modules/
folder of the Formbird install.
For example, to enable the moment
module:
-
Download
moment
usingnpm
or from it's website https://momentjs.com/. -
Copy the file
moment.js
to the following server location:./server/public/vendor/custom-component-modules/moment/
The file should appear as follows: ./server/public/vendor/custom-component-modules/moment/moment.js
Tip: This process is not limited to modules alone. Other files including CSS and template files may be installed in the same manner.
Once the required modules are installed, use one of the following methods to access it from your Component.
Using Component External Library Documents
You can specify the external library on your UI Component using the Component External Library Documents
field as discussed in section Components Structure - Component dependencies
. This field provides a list of available libraries to choose from, and can be extended with any additional libraries you may require. This is the preferred approach of accessing External Libraries from a UI Component.
To extend the list with additional libraries, first ensure the library files are installed on the server, and then use the External Component Library Reference
Template (eefe2d60-8e16-11e8-9fe7-4fe2d6e868a0
) to create an entry for the library. An example entry for the external library proj4
follows:
Field | Value |
---|---|
Name | proj4 |
Description | Projection library used by mapping components |
Relative Library Path | vendor/custom-component-modules/proj4/proj4.js |
Note that the "Relative Library Path" value begins with "vendor/custom-component-modules/". Make sure this is included in your own "Relative Library Path" values.
Using Lazy Loading
Lazy loading is a technique for loading files at the point-in-time when they are needed rather than at the beginning of the process. This technique can be used to speed up the initial load time of a component by only loading what is needed to start with. Lazy loading of external libraries may be of some benefit to you if it is seldom used, for example it is an optional part of the UI Component that is rarely activated by a user, or if it is an interchangeable library/file based on configurable options in your component.
To lazy load an external library, first ensure the library files are installed on the server and then use the ocLazyLoad
service to perform the task. For example:
var proj4 = $ocLazyLoad.load({name: 'proj4', files: ['vendor/custom-component-modules/proj4/proj4.js']});
proj4.then(
function(){
logger.info("proj4 loaded............");
},function(err){
logger.error("error lazy loading proj4: " + err);
}
);
The following example is sourced from the sc-note-box
component's Load Function:
function(){
if( typeof scope.tplItem.readOnly === 'undefined'
|| scope.tplItem.readOnly === null ){
scope.readOnly=false;
}else{
scope.readOnly = scope.tplItem.readOnly;
}
if( !(typeof scope.tplItem.enabled === 'undefined'
|| scope.tplItem.enabled === null) ){
scope.readOnly = !scope.tplItem.enabled;
}
if( typeof scope.tplItem.visible === 'undefined'
|| scope.tplItem.visible === null ){
scope.visible=true;
}else{
scope.visible = scope.tplItem.visible;
}
if( typeof scope.tplItem.noteBoxRows === 'undefined'
|| scope.tplItem.noteBoxRows === null ){
scope.noteBoxRows=3;
}else{
scope.noteBoxRows = scope.tplItem.noteBoxRows;
}
if( typeof scope.tplItem.disableSave === 'undefined'
|| scope.tplItem.disableSave === null ){
scope.disableSave=false;
}else{
scope.disableSave = scope.tplItem.disableSave;
}
var ModifiedFieldService = $injector.get('ModifiedFieldService');
var timeOutDelay=1000;
var componentElement;
var noteBoxDivResizable;
var deviceDetect = $ocLazyLoad.load({name: 'deviceDetect',
files: ['vendor/custom-component-modules/device-detect/devicedetect.js']});
deviceDetect.then(
function(){
logger.info("device detect loaded............");
$timeout(function() {
componentElement =element.find('textarea');
logger.info("Browser name: "+detectBrowser().browser);
if (detectBrowser().browser === "Chrome"
|| detectBrowser().browser === "Firefox"
|| detectBrowser().browser === "Safari") {
//continue for default textarea expandable1
}else{
//If textarea is not resizable lazy load jquery ui resizable
var customLazyLoadA = $ocLazyLoad.load({name: 'customLazyLoadA',
files: ['vendor/custom-component-modules/jquery-ui-resizable/jquery-ui.css'], serie: true});
customLazyLoadA.then(function(){
var customLazyLoad = $ocLazyLoad.load({name: 'customLazyLoad',
files: ['vendor/custom-component-modules/jquery-ui-resizable/jquery-ui.js'], serie: true});
customLazyLoad.then(function(){
$timeout(function(){
logger.info("jquery ui loaded............");
if(scope.visible){
initializeExpandable();
}
});
scope.$watch('tplItem.visible', function(newValue, oldValue) {
if(newValue){
setTimeout( function() {
initializeExpandable();
$(element).find('.ui-wrapper').css('width',
$(element.parent()).width()-2);
$(element).find('textarea').css('width',
$(element.parent()).width()-8);
}, 200);
}
}, true);
$('#left_close').click(function() {
setTimeout( function() {
if(!scope.tplItem.visible){
return;
}
initializeExpandable();
$(element).find('.ui-wrapper').css('width',
$(element.parent()).width()-2);
$(element).find('textarea').css('width',
$(element.parent()).width()-8);
}, 500);
});
function initializeExpandable(){
$(componentElement).resizable({
//handles: 'n,s,e,w',
maxWidth: $(element.parent()).width(),
minWidth: $(element.parent()).width(),
create: function( event, ui ) {
var textElement=$(event.target).find('textarea');
$(textElement).css({"width":($(event.target).width())+"px",
"height":($(event.target).height())+"px"});
$(textElement).css("border","none");
noteBoxDivResizable=event.target;
if(scope.readOnly) {
$(noteBoxDivResizable).css({'background-color':'#f1f1f1',
'cursor':'not-allowed'});
} else {
$(noteBoxDivResizable).css({'background-color':'white',
'cursor':''});
}
$('div[class*="ui-icon-gripsmall-diagonal-se"]').css( {
'background-position':'-80px -228px',//-80px -228px;
'width':'10px',
'height':'9.5px',
'opacity':'0.6'
});
},
stop: function( event, ui ) {
$(ui.element.context).css({"width":($(ui.element[0]).width())+"px",
"height":($(ui.element[0]).height())+"px"});
}
});
}
},function(err){
logger.info("error on lazy load jquery ui js");
logger.info(err);
});
},function(err){
logger.info("error on lazy load jquery uiA CSS");
logger.info(err);
});
}
});
},function(err){
logger.info("error on lazy load device detect");
logger.info(err);
});
//This is watched function for readOnly field
scope.$watch("readOnly", function(value) {
$timeout(function() {
if(value){
$(element).addClass('disabled').addClass('readonly');
$(element.parent()).addClass('disabled').addClass('readonly');
$(noteBoxDivResizable).css({'background-color':'#f1f1f1',
'cursor':'not-allowed'});
}else{
$(element).removeClass('disabled').removeClass('readonly');
$(element.parent()).removeClass('disabled').removeClass('readonly');
$(noteBoxDivResizable).css({'background-color':'white','cursor':''});
}
timeOutDelay=300;
},timeOutDelay);
}, true);
}
In the above example, external libraries devicedetect
and jquery-ui
are lazy loaded to assist with the display of the sc-note-box
component.
Refer to ocLazyLoad
's documentation (at https://oclazyload.readme.io/docs/oclazyload-service) for further details on its usage.