This documentation supports the 20.08 version of BMC Helix Platform. 
To view an earlier version, select 20.02 from the Product version menu.

Creating custom view components for record editor

Record editor is a view component that is used to create or edit record instances. Record editor may contain field components (for example, select group, dropdown, attachment) which are available on the View designer palette. Record editor field component is a view component that can be embedded in a record editor.

To create a record editor field component, perform the following steps:

  1. Create a directive for record editor field component.

  2. Create design time directive.
  3. Create a design manager for view component.

  4. Create model for record editor field component.

  5. Register the record editor field component.

Creating record editor field component directive

The default controller, RxRecordEditorFieldComponentController, implements the default logic required for a record editor field component. To run the default logic you must use the controller init method and configure RxRecordEditorFieldComponentController injectable $scope and $element locals. The RxRecordEditorFieldComponentController#init performs the following tasks:

  • Updates fieldDefinition and fieldInstance properties on the $scope object
  • Updates fieldInstance.value based on propertiesByName.value expression
  • Sets component API

Example of directive for Regular Expression Text component:

angular.module('com.example.samplelibrary.view-components.regular-expression-text')
    .directive('comExampleSamplelibraryRegularExpressionTextField', function ($controller) {
        return {
            restrict: 'E',
            templateUrl: 'scripts/view-components/regular-expression-text-field/com-example-samplelibrary-regular-expression-text-field.directive.html',
 
            scope: {
                rxConfiguration: '='
            },
 
            require: '^form',
 
            link: function ($scope, $element, attrs, formController) {
                var fieldComponentCtrl = $controller('RxRecordEditorFieldComponentController', {
                    $scope: $scope,
                    $element: $element
                });
 
                fieldComponentCtrl.init();
                $scope.form = formController;
            }
        };
    });

Record editor can be displayed in two states, READ and EDIT. Every record editor field component should be correctly rendered in both states.

The following code illustrates a directive template:

div ng-if="!rxConfiguration.propertiesByName.hidden"
     on="rxConfiguration.propertiesByName.state"
     ng-switch>
    <div ng-switch-when="READ">
        <div class="d-textfield">
            <label class="d-textfield__label">
                <span class="d-textfield__item">{{::fieldDefinition.name}}</span>
            </label>
 
            <p>{{fieldInstance.value}}</p>
        </div>
    </div>
 
    <div ng-switch-when="EDIT">
        <div class="d-textfield"
             ng-class="{
                'd-textfield_required': fieldDefinition.fieldOption == 'REQUIRED',
                'd-textfield_invalid' : form[fieldDefinition.name].$dirty && form[fieldDefinition.name].$invalid
             }">
            <label class="d-textfield__label">
                <span class="d-textfield__item">{{rxConfiguration.propertiesByName.label}}</span>
 
                <input type="email"
                       name="{{fieldDefinition.name}}"
                       ng-model="fieldInstance.value"
                       ng-disabled="rxConfiguration.propertiesByName.disabled"
                       maxlength="{{rxConfiguration.propertiesByName.maxLength}}"
                       class="d-textfield__input"
                       ng-pattern="rxConfiguration.propertiesByName.regularExpression"
                       ng-required="fieldDefinition.fieldOption == 'REQUIRED'">
            </label>
            <p class="d-error"
               ng-if="form[fieldDefinition.name].$dirty && form[fieldDefinition.name].$invalid">
                <span class="d-error__message">
                    Invalid Value
                </span>
            </p>
        </div>
    </div>
</div>

Creating design time directive

Design time directive represents how a view component is displayed on the canvas in the View designer and its usage. A custom angular directive to use a field component in the View designer must have isolated scope. You can use the the default RxRecordEditorFieldComponentDesignController controller. The directive gets componentDefinitionId and model properties from rxConfiguration.

The following sample code illustrates a directive that uses the default RxRecordEditorFieldComponentDesignController controller:

angular.module('com.example.samplelibrary.view-components.regular-expression-text')
    .directive('comExampleSamplelibraryRegularExpressionTextFieldDesign', function ($controller) {
        return {
            restrict: 'E',
            templateUrl: 'scripts/view-components/regular-expression-text-field/com-example-samplelibrary-regular-expression-text-field-design.directive.html',
 
            scope: {
                rxConfiguration: '='
            },
 
            controller: function ($scope) {
                $controller('RxRecordEditorFieldComponentDesignController', {$scope: $scope});
            }
        };
    });

Creating design manager

Design manager is used to prepare model configurations and create the model instance for a record editor field component. rxRecordEditorFieldComponentDefaultDesignManager is the default manager class for record editor field component that defines the standard steps to create the model. You must create a instance of the default manager and expose getModel method.

Sample code:

angular.module('com.example.samplelibrary.view-components.regular-expression-text')
    .factory('comExampleSamplelibraryRegularExpressionTextFieldDesignManager', [
        'rxRecordEditorFieldComponentDefaultDesignManager',
        function (rxRecordEditorFieldComponentDefaultDesignManager) {
            // create manager instance
            var designManager = new rxRecordEditorFieldComponentDefaultDesignManager();
  
            return {
                getModel: function (componentDefinition) {
                    // expose getModel method
                    return designManager.getModel(componentDefinition);
                }
            };
        });

If you need any customization, you can extend the default design manager using the following methods:

  • getRxInspector—returns configuration for inspector
  • getRxData—returns object with rxData configuration
  • getRxConfig—returns model configuration
  • getModel—returns model instance

 Sample code:

angular.module('com.example.samplelibrary.view-components.regular-expression-text')
        .factory('comExampleSamplelibraryRegularExpressionTextFieldDesignManager', [
            'rxRecordEditorFieldComponentDefaultDesignManager', 
            'comExampleSamplelibraryRegularExpressionTextFieldModel', 
            function (rxRecordEditorFieldComponentDefaultDesignManager,
                      RegularExpressionTextFieldModel) {
                var RegularExpressionTextFieldDesignManager = rxRecordEditorFieldComponentDefaultDesignManager.extend({
                    // rewriting getModel method
                    getModel: function (componentDefinition) {
                        // RegularExpressionTextFieldModel - custom model
                        // still use default getRxConfig method for getting model configurations
                        return new RegularExpressionTextFieldModel(this.getRxConfig(componentDefinition));
                    }
                });
 
            var designManager = new RegularExpressionTextFieldDesignManager();
 
            return {
                getModel: function (componentDefinition) {
                    return designManager.getModel(componentDefinition);
                }
            };
        });

Creating model for record editor field component

rxRecordFieldDefinitionModel is the default model for building field components. You can extend the default model or override the methods of the default model to create a custom model to add custom editors, user input validations, and changes to JSON structure.

rxRecordFieldDefinitionModel methods

The record editor field component default model consists of the following methods:

MethodDescriptionReturn value
 reateListenersCreates handlers for model data and parent model value changes 
onFieldDefinitionChanged

Called when changes to field ID changes and  component initialization

Parameters:

{Object} fieldDefinition (new field definition)

{(Object|undefined)} previousFieldDefinition  (old field definition)

{Promise} a promise that is resolved when default preparation finished
getFieldNameOptionsGets a list of record editor fields supported by current field model{Promise} a promise that is resolved with fieldNameOptions
getRecordDefinitionGets the record definition associated with the record editor{Object}
getRecordEditorIdGets the ID of the record editor view component{String}
getRecordEditorStateGets the current record editor state{('EDIT'|'CREATE')}
getRecordDefinitionNameGets the name of the record definition bound to the record editor{String}
getCurrentFieldDefinitionGets the field definition for a selected Field ID{Promise} a promise is resolved with field definition
setInspector

Refreshes the inspector

Parameters:

{Object} rxInspector

 
getRxInspectorGets the default field inspector configuration{Promise} a promise that is resolved with rxInspector configuration

Examples of overriding rxRecordFieldDefinitionModel methods

The following sample code is an example of overriding rxRecordFieldDefinitionModel by comExampleSamplelibraryRegularExpressionTextFieldModel:

angular.module('com.example.samplelibrary.view-components.regular-expression-text')
    .factory('comExampleSamplelibraryRegularExpressionTextFieldModel', [
        'rxRecordEditorFieldComponentDesignModel', 
        function (rxRecordEditorFieldComponentDesignModel) {
            return rxRecordFieldDefinitionModel.extend({
                describeViewComponent: function () {},
                getRxInspector: function () {},
                validate: function () {}
            });
        }
    ]);

The following table provides examples of overriding rxRecordFieldDefinitionModel methods:

MethodDescriptionSample code

getRxInspector

This method is can be overridden to add a new editor to the inspector that is used by the regularExpression property.
getRxInspector: function () {
    return rxRecordEditorFieldComponentDesignModel.prototype.getRxInspector.call(this)
        .then(function (rxInspector) {
            rxInspector.inputs.rxData.regularExpression = {
                label: 'Input Format',
                type: 'com-example-samplelibrary-inspector-input-with-dropdown',
                group: 'general',
                index: 3,
                tooltip: 'It accepts regular expression as value'
            };
 
            rxInspector.inputs.rxData.value.index = 4;
            rxInspector.inputs.rxData.disabled.index = 5;
            rxInspector.inputs.rxData.hidden.index = 6;
 
            return rxInspector;
        });
}

describeViewComponentThis method can be overridden to add a new property, regualrExpression, to the view component model.
describeViewComponent: function () {
    var descriptor = rxRecordFieldDefinitionModel.prototype.describeViewComponent.call(this);
 
    descriptor.propertiesByName.regularExpression = this.get('rxData').regularExpression || '';
 
    return descriptor;
},
validateThis method can be overridden to add validation for the regularExpression field.
validate: function () {
    var me = this;
 
    /**
     * call validate method from rxRecordFieldDefinitionModel to get default validation issues for the field
     */
    return rxRecordFieldDefinitionModel.prototype.validate.call(this)
        .then(function (validationIssues) {
            validationIssues = validationIssues || [];
 
            /**
             * Check if user input is valid RegExp pattern
             * reference http://stackoverflow.com/a/17250859
             */
            try {
                // eslint-disable-line no-new
                new RegExp(me.prop('rxData/regularExpression')); 
            } catch (e) {
                validationIssues.push({
                    elementId: me.get('id'),
                    elementName: 'Regular Expression Text',
                    componentProperty: true,
                    propertyName: 'regularExpression',
                    type: 'error',
                    message: 'Regular Expression field should be a valid RegExp pattern'
                });
            }
 
            return validationIssues;
        });
}

Registering a record editor field component

Record editor field component has the following additional properties as compared to a generic view component:

  • canBeEmbeddedInRecordEditor—must set to true to embed in record editor
  • supportedFieldResourceTypes—an array of field data types from RX_RECORD_DEFINITION.dataTypes enumeration

If required, you can modify the default properties. You can get the default properties by using the rxRecordEditorFieldComponentConfiguratorProvider#getFieldComponentDescriptorDefaults method.  

The following is list of properties that are returned by getFieldComponentDescriptorDefaults method:

PropertyDescription
recordDefinition

Defines expression pointing to the record definition.

This is a mandatory field for record editor field component.

recordInstanceDefines expression pointing to the record instance
fieldIdDefines field ID bound to the component
disabledDefines an expression that determines whether a component should be disabled
hidden
Defines an expression that determines whether a component should be hidden
labelDefines a localizable label
value
Defines an expression that defines the field value

The following sample code illustrates how to register a record editor field component:

rxViewComponentProvider.registerComponent({
    name: 'Regular Expression Text',
    canBeEmbeddedInRecordEditor: true,
    supportedFieldResourceTypes: [RX_RECORD_DEFINITION.dataTypes.character.resourceType],
    ...
    propertiesByName: rxRecordEditorFieldComponentConfiguratorProvider
        .getFieldComponentDescriptorDefaults()
        .propertiesByName
        .concat([
            {
                name: 'regularExpression',
                type: 'string',
                isConfig: true
            }
        ])
});

Section 508 compliance

All BMC built-in view components in BMC Helix Platform and all BMC built applications running on BMC Helix Platform are Section 508 compliant and are accessible by the visually impaired. 


Note

  • BMC certifies web clients that are using supported versions of browsers with the JAWS18 screen reader.
  • BMC Helix Platform uses WAI-ARIA 1.1 specification to improve interoperability with assistive technologies.

Related topics

Creating custom view components

Example of creating a custom view component

Creating custom actions 

Enabling and downloading logs from BMC Helix Innovation Studio

Enabling browser logging in a Digital Service application

Naming conventions for angular objects

Was this page helpful? Yes No Submitting... Thank you

Comments