This section discusses customizations that you can make to the sample project. They demonstrate how you define a new type that provides links to a mapping service such as Google Maps. The first step is defining a JavaScript renderer and defining a custom data type. (
Rendering
is the application of a friendly user interface for the task's interface input and output messages.) Next, modify the project's metadata files that allow these additions to be discovered.
Note
: The Process Server executes your project's
.avcconfig
files in alphabetical order. You can see this order by selecting
Catalog | Resources | Central Configs
from within Process Console. If one of your files is inadvertently overriding another, you will need to change the file's name to change the execution order.
Note
: When implementing a custom renderer, you must add the
ae-sf-renderer-container
class to the root element (that is, to the
<div>
) of your renderer. If you do not, your interface will open in a new window.
Creating a custom data type requires that the new type be defined in a metadata file and a renderer be defined to display it at both design- and runtime.
In the example,
{$sample.project}/config/MapItRenderer.js
renders an HTML anchor with the text "Map It" and the
href
of the anchor is a URL to a mapping service configured in the datatype options.
Code Example: Renderer JavaScript
(function($) {
activevos.util.createAvosPackage("my.custom.namespace");
function MyCustomRenderer(aDataValueCollection) {
this.renderField = function(aContainerElement,
ajQueryContext, aFieldName, aFieldDataValue)
{
// do something
};
};
my.custom.namespace.MyCustomRenderer = MyCustomRenderer;
})(jQuery);
This example is a skeleton for a custom renderer and it only requires that the
renderField
function be implemented. The second line defines a unique package name or namespace for the renderer; this is similar to a package name in Java.
The lines shown in bold begin the definition of the custom renderer function. It accepts an argument (shown in the next example) that contains all of the data for the screen. It also defines the
renderField
property, which is also a function and which renders the data. The
renderField
arguments are the HTML elements that contain your custom rendered field, the jQuery context, the field name being rendered, and the field value (see the
AeScreenFlowDataValue
example later in this topic).
Code Example: AeScreenFlowDataValuesCollection Function
function AeScreenFlowDataValuesCollection(){
/**
* @returns {Array} list of AeScreenFlowDataValue objects.
*/
this.getDataValues = function() {};
/**
* @returns {boolean} true if named data value holder
* exists.
*/
this.hasDataValue = function(aName) {};
/**
* Returns a type by name or null if not found.
* @param {String}: aName name of data value
* @returns {AeScreenFlowDataValue}; the data value or null
* if not found.
*/
this.getDataValue = function(aName) {};
}
Code Example: AeScreenFlowDataValue Function
function AeScreenFlowDataValue(aType, aName, aValue, aRenderingTypeName) {
/**
* Gets the rendering type name. If the rendering type is not
* set, it returns the type.
*/
this.getRenderingTypeName = function() {};
/**
* Gets the name of the field.
*/
this.getName = function() {};
/**
* Gets the value of the field.
*/
this.getValue = function() {};
/**
* @returns {AeDataOptions} Collection of AeOption objects.
*/
this.getOptions = function() {};
/**
* Returns option value.
* /
this.getOptionValue = function(aName) {};
/**
* @returns {boolean} true if field is readonly.
*/
this.isReadOnly = function() {};
}
After you define the renderer, you can define the custom type. The
{$sample.project}/config/custom-types.xml
sample project defines a new type named
mapit
. It is bound to the
MapitRenderer.js
custom renderer. To enable this type for the sample application, uncomment the
type
element.
Using JavaScript Libraries
When a custom renderer uses a JavaScript library, it can import it dynamically instead of including it within an
avcconfig
file. For example, you could load a library named
dataTable
as follows:
var loadDataTablePlugin = $.dataTable ? null :
myProject.loadScript(/path/to/datatable/js/file, $);
$.when(loadDataTablePlugin).done( function() {
// Use dataTable here}
);
After creating the custom types and renderers, you need to make them available for your host application. The project does this by using the
mapit
type in the custom
contacts
entity to provide a Google Map for the contact. In the
{$sample.project}/host_env/contacts_detail.xml
file, uncomment the field definition for
Full Address.
Code Example: Full Address Field Definition
<host:field label="Full Address" name="FullAddress"
readonly="true" required="false" type="mapit">
<host:options>
<host:option name="mapping-provider"
hide="true">http://www.bing.com/maps/default.aspx?q=</host:option>
</host:options>
...
The
mapping-provider
attribute's value was changed to use Microsoft Bing as the mapping provider instead of Google Maps. The
mapping-provider
option is hidden so that guide developers cannot edit it. If the
hide
attribute was set to false or removed, guide developers could change the
mapping-provider
in the guide designer.
After altering the entity definition, redeploy the sample project using the packaged BPRD file, as follows:
Navigate to the guide designer and open the Sales Call Follow up guide.
Open the Click continue after your verification step and add a read-only field for Full Address.
Save and publish the guide.
After you launch the updated guide, a new
Map It
link appears that opens a new browser tab when clicked.
A render class can implement the
validateField
JavaScript function to validate data. This function is called when the user presses an action button.
This function's definition is:
validateField(aFieldDataValue, aJQueryContext)
aFieldDataValue
: An
AeScreenFlowDataValue
instance.
aJQueryContext
: A jQuery object to be used as context for validation. Any jQuery plugins imported through
.avcconfig
are available here.
this.validateField = function(aFieldDataValue, aJQueryContext) {
var $ = aJQueryContext;
var salutation = aFieldDataValue.getValue().salutation;
if ( salutation.name.$t === 'chester'){
var errorMsg = "Cant equal chester";
return { result: false, message: errorMsg};
}
return { result: true };
}