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

Example of creating a custom view component

Consider a custom view component named Star Rating. The Star Rating view component allows the user to choose the rating by a click on a star. The rating is stored in a record instance field after the click on a star.

Note

You must ensure that you follow naming conventions (namespacing) for all angular object names and all HTML filenames in shared code. See Naming conventions for angular objects.

To create Star Rating view component, perform the following steps:

  1. Create basic configurations.

  2. Configure component property.

  3. Create design time view component.

  4. Create design manager and model.

  5. Validate model.

  6. Create Properties pane editor.

  7. Enhance view component.

  8. Interact with other view components.

Creating basic configurations

  1. Define an angular module for the view component in the star-rating.module.js file.

    Sample code:

    angular.module('com.example.samplelibrary.view-components.star-rating', [
        'com.bmc.arsys.rx.standardlib.view-component',
        'com.bmc.arsys.rx.standardlib.record.definition'
    ]);
  2. Create an angular directive that represents how the component is displayed in a view definition in the star-rating.directive.js file.

    Sample code:

    angular.module('com.example.samplelibrary.view-components.star-rating')
        .directive('comExampleSamplelibraryStarRating', function () {
            return {
                restrict: 'E',
                template: '<h1>Star Rating Component</h1>',
    
                scope: {
                    rxConfiguration: '='
                }
            };
        });
    
    
  3. Register the view component in the star-rating.config.js file.

    Sample code:

    angular.module('com.example.samplelibrary.view-components.star-rating')
        .config(function (rxViewComponentProvider) {
            var starRatingDescriptor = {
                name: 'Star Rating',
                group: 'Basic Components',
                icon: 'star',
                type: 'com-example-samplelibrary-star-rating',  // the name of runtime directive
                bundleId: 'com.example.samplelibrary'
            };
    
            rxViewComponentProvider.registerComponent(starRatingDescriptor);
        });
  4. If you are creating the view component for a smart library, add the dependency of the view component module in the main library module.
    Sample code:

    // com.example.samplelibrary.module.js
    angular.module('com.example.samplelibrary', [
        'com.example.samplelibrary.view-components.star-rating'
    ]);
    

    If you are creating the view component for an application, add the dependency of the view component module in the extension module of the application.
    Sample code:

    // com.example.myapplication-ext.module.js
    angular.module('com.example.myapplication-ext', [
        'com.example.myapplication.view-components.star-rating'
    ]);
    

After these basic steps are completed and the com.example.samplelibrary bundle is deployed, you can view the Star Rating view component in the View designer as shown in the following image:

Configuring component property

You can add the view component configuration properties during component registration.

The Star Rating view component requires the following properties:

  • Record Definition Name—record definition name
  • Record Instance ID—ID of the record instance in which the star rating will be saved
  • Field ID—ID of the field in which the star rating will be saved
  • Stars—number of stars to show

Sample code in star-rating.config.js file:

star-rating.config.js
angular.module('com.example.samplelibrary.view-components.star-rating').config(function (rxViewComponentProvider) {
    var starRatingDescriptor = {
        name: 'Star Rating',
        group: 'Basic Components',
        icon: 'star',
        type: 'com-example-samplelibrary-star-rating',  // the name of runtime directive
        bundleId: 'com.example.samplelibrary',

        // define component properties
        propertiesByName: [
            {
                name: 'recordDefinitionName',
                isConfig: true,
				enableExpressionEvaluation: true,
                isRequired: true
            },
            {
                name: 'recordInstanceId',
                isConfig: true,
				enableExpressionEvaluation: true,
                isRequired: true
            },
            {
                name: 'fieldId',
                isConfig: true,
				enableExpressionEvaluation: true,
                isRequired: true
            },
            {
                name: 'stars',
                isConfig: true,
				enableExpressionEvaluation: true,
                isRequired: true
            }
        ]
    };

    rxViewComponentProvider.registerComponent(starRatingDescriptor);
});

All properties marked with isConfig flag are available in the View designer  Properties pane.

All properties marked with isRequired flag are validated.

Creating design time view component

Design time view component is a regular angular directive that represents the view component on the View designer canvas.

  1. Create design time directive in star-rating-design.directive.js file.

    Sample code:

    star-rating-design.directive.js
    angular.module('com.example.samplelibrary.view-components.star-rating').directive('comExampleSamplelibraryStarRatingDesign', function () {
        return {
            restrict: 'E',
            templateUrl: 'scripts/com.example.samplelibrary/view-components/star-rating/com-example-samplelibrary-star-rating-design.directive.html',
    
            scope: {
                rxConfiguration: '='
            },
    
            link: function ($scope) {
                // view component configuration will be stored in $scope.rxConfiguration.model
    
                updateStars();
    
                // subscribe to rxData property change
                $scope.rxConfiguration.model.on('change:rxData', updateStars);
    
                function updateStars() {
                    var stars = Number($scope.rxConfiguration.model.prop('rxData/stars'));
                }
    
                $scope.getStars = function (stars) {
                    return new Array(stars);
                };
            }
        };
    });

    Add the following code in com-example-samplelibrary-star-rating-design.directive.html file:

    com-example-samplelibrary-star-rating-design.directive.html
    <span ng-repeat="star in getStars(stars) track by $index" class="d-icon-star"></span>
  2. Register the design time view component.

    angular.module('com.example.samplelibrary.view-components.star-rating').config(function (rxViewComponentProvider) {
        var starRatingDescriptor = {
            // ...       
    
            designType: 'com-example-samplelibrary-star-rating-design' // register design directive     
        };
    
        rxViewComponentProvider.registerComponent(starRatingDescriptor);
    });

    After the above steps are completed and the bundle is redeployed, the Star Rating view component is displayed in the View designer canvas as shown in the following image:

Creating design manager and model

You can create a model and design manager for the view component, if it requires more complex configurations in design time.

  1. Create model for the view component in star-rating-model.service.js file. The model should extend the rxViewComponentModel. The following code illustrates a simple configuration:

    star-rating-model.service.js
    angular.module('com.example.samplelibrary.view-components.star-rating').factory('comExampleSamplelibraryStarRatingModel', function (rxViewComponentModel) {
        return rxViewComponentModel.extend({});
    });

    The following code illustrates how to load a record definition every time changes the record definition name configuration property.

    star-rating-model.service.js
    angular.module('com.example.samplelibrary.view-components.star-rating').factory('comExampleSamplelibraryStarRatingModel', function (rxViewComponentModel, rxRecordDefinitionResource) {    return rxViewComponentModel.extend({
            initialize: function () {
                // launch parent initialize method
                rxViewComponentModel.prototype.initialize.apply(this, arguments);
     
                // add listener for rxData
                this.listenTo(this, 'change:rxData', this._onChangeRxData);
     
                this._initRecordDefinition();
            },
     
            _initRecordDefinition: function () {
                if (this.prop('rxData/recordDefinitionName')) {
                    var me = this;
                     
                    // load Record Definition
                    rxRecordDefinitionResource.get(this.prop('rxData/recordDefinitionName')).then(function (recordDefinition) {
                        me.recordDefinition = recordDefinition;
                    }).catch(function () {
                        me.recordDefinition = null;
                    });
                } else {
                    this.recordDefinition = null;
                }
            },
     
            _onChangeRxData: function (model, rxData, changedProperty) {
                if (changedProperty.propertyPath === 'rxData/recordDefinitionName') {
                    this._initRecordDefinition();
                }
            }
        });
    });
  2. Create custom design manager in star-rating-design.service.js file. The following code illustrates a simple configuration for design manager:

    star-rating-design.service.js
    angular.module('com.example.samplelibrary.view-components.star-rating').factory('comExampleSamplelibraryStarRatingDesign', function () {
        return {};
    });

    The following code illustrates design manager that implements the getModel method:

    star-rating-design.service.js
    angular.module('com.example.samplelibrary.view-components.star-rating').factory('comExampleSamplelibraryStarRatingDesign', function (comExampleSamplelibraryStarRatingModel, rxGUID, RX_DEFINITION_PICKER) {
        function getRxConfig(componentDefinition) {
            return {
                id: componentDefinition.guid || rxGUID.generate(),
                type: componentDefinition.type,
                rxData: getRxData(componentDefinition),
                rxInspector: getRxInspector()
            };
        }
     
        function getRxData(componentDefinition) {
            return {
                recordDefinitionName: componentDefinition.propertiesByName.recordDefinitionName,
                recordInstanceId: componentDefinition.propertiesByName.recordInstanceId,
                fieldId: componentDefinition.propertiesByName.fieldId,
                stars: componentDefinition.propertiesByName.stars || 5
            };
        }
     
        function getRxInspector() {
            return {
                inputs: {
                    rxData: {
                        recordDefinitionName: {
                            label: 'Record Definition Name',
                            type: 'rx-inspector-definition-picker', // special editor for selecting definitions
                            definitionType: RX_DEFINITION_PICKER.definitionTypes.regularRecord.type, // define which definition user can select
                            group: 'general',
                            index: 1
                        },
                        recordInstanceId: {
                            label: 'Record Instance ID',
                            type: 'rx-inspector-expression-node-field',
                            group: 'general',
                            index: 2
                        },
                        fieldId: {
                            label: 'Field ID',
                            type: 'rx-inspector-expression-node-field',
                            group: 'general',
                            index: 3
                        },
                        stars: {
                            label: 'Stars',
                            type: 'rx-inspector-expression-node-field',
                            group: 'general',
                            index: 4
                        }
                    }
                },
                groups: {
                    general: {
                        label: 'General',
                        index: 1
                    }
                }
            };
        }
     
        return {
            // should return a model instance
            getModel: function (componentDefinition) {
                return new comExampleSamplelibraryStarRatingModel(getRxConfig(componentDefinition));
            }
        };
    });
  3. Register the design manager service in star-rating.config.js file.

    star-rating.config.js
    angular.module('com.example.samplelibrary.view-components.star-rating').config(function (rxViewComponentProvider) {
        var starRatingDescriptor = {
            // ...
            designManagerService: 'comExampleSamplelibraryStarRatingDesign'
        };
      
        rxViewComponentProvider.registerComponent(starRatingDescriptor);
    });

    After this step is complete and the bundle is redeployed, you can view that the record definition name field is displayed as a dropdown.

Validating model

The model is responsible for the view component configuration property value validation in design time. The following code shows how to add the validation to the Stars configuration property:

star-rating-model.service.js
angular.module('com.example.samplelibrary.view-components.star-rating').factory('comExampleSamplelibraryStarRatingModel', function (rxViewComponentModel, rxRecordDefinitionResource) {
    return rxViewComponentModel.extend({
        // ... 
 
        validate: function () {
            var me = this;
 
            // execute default validation method
            return rxViewComponentModel.prototype.validate.apply(this, arguments).then(function (validationIssues) {
                // check that the number of stars is at least 5
                if (me.prop('rxData/stars') < 5) {
                    validationIssues.push({
                        elementId: me.get('guid'),
                        elementName: 'Star Rating',
                        propertyName: 'stars',
                        type: 'error',
                        message: 'The number of stars should be greater or equal to 5.'
                    });
                }
 
                return validationIssues;
            });
        }
    });
});

After you redeploy the bundle, you can view a validation error message if the number of stars is less than 5.

Creating Properties pane editor

Create an editor that helps a user to select a field in which the rating is stored. In this example, let us use a record definition Record with rating that has an integer Rating field.

The Properties pane editor is a regular angular directive that should implement the UI where the user can edit the model property. The directive has the following properties configured on its scope:

  • $scope.cellmodel that stores all component properties
  • $scope.path—defines the path to the property whose value are edited
  • $scope.options—all options which are defined in the rxInspector configuration for the field

    For example:

    {
    	label: 'Field Id',
    	type: 'rx-inspector-expression-node-field',
        group: 'general',
        index: 3
    }

The following code illustrates a simple Properties pane editor implementation:

angular.module('com.example.samplelibrary.view-components.star-rating').directive('comExampleSamplelibraryInspectorStarRatingFieldSelect', function () {
    return {
        restrict: 'E',
        templateUrl: 'scripts/com.example.samplelibrary/view-components/star-rating/editor/com-example-samplelibrary-inspector-star-rating-field-select.directive.html',

        link: function ($scope) {
			// $scope.path - e.g. 'rxData/fieldId'
			
			// get current model value
            var currentModelValue = $scope.cell.get($scope.path);
 
			// set new value
			$scope.cell.get($scope.path, 536870913);
        }
    };
});

The following code illustrates the full implementation for the Properties pane editor:

inspector-star-rating-fied-select.directive.js
angular.module('com.example.samplelibrary.view-components.star-rating').directive('comExampleSamplelibraryInspectorStarRatingFieldSelect', function (RX_RECORD_DEFINITION) {
    return {
        restrict: 'E',
        templateUrl: 'scripts/com.example.samplelibrary/view-components/star-rating/editor/com-example-samplelibrary-inspector-star-rating-field-select.directive.html',

        link: function ($scope) {
            $scope.data = {
                fields: [],
                selectedField: null
            };

            init();

            function init() {
                initializeFields();

                // reinitialize fields when user change Record Definition
                $scope.$watch('cell.recordDefinition', initializeFields);

                $scope.$watch('data.selectedField', function (newValue) {
                    if (newValue) {
                        // set field id to the model
                        $scope.cell.prop($scope.path, $scope.data.selectedField.id);
                    }
                }, true);
            }

            function initializeFields() {
                if ($scope.cell.recordDefinition) {
                    $scope.data.fields = getFields();

                    $scope.data.selectedField = _.find($scope.data.fields, {
                        id: Number($scope.cell.prop($scope.path))
                    });
                } else {
                    $scope.data.fields = [];
                    $scope.data.selectedField = null;
                }
            }

            // get all integer fields from the selected Record Definition
            function getFields() {
    			return _($scope.cell.recordDefinition.fieldDefinitions)
        			.filter({
            			resourceType: RX_RECORD_DEFINITION.dataTypes.integer.resourceType
        			})
        			.map(function (fieldDefinition) {
            			return {
                			id: fieldDefinition.id,
                			name: fieldDefinition.name
            			};
        			})
        			.value();
			}
        }
    };
});

The following code is a template for the Properties pane editor directive:

com-example-samplelibrary-inspector-star-rating-field-select.directive.html
<label ng-class="options.attrs.label.class">
    <rx-tooltip tooltip="options.tooltip"></rx-tooltip>
    {{options.label}}:
</label>

<div ng-if="data.fields.length">
    <select class="select" ng-options="field.name for field in data.fields track by field.id"
            ng-model="data.selectedField"></select>
</div>

<div ng-if="!data.fields.length">
    There are no fields for select
</div>

To use the created inspector editor, set the type property to the name of the directive in the inspector configuration:

star-rating-design.service.js
angular.module('com.example.samplelibrary.view-components.star-rating').factory('comExampleSamplelibraryStarRatingDesign', function (comExampleSamplelibraryStarRatingModel,
                                                                                                                                     rxGUID,
                                                                                                                                     RX_DEFINITION_PICKER) {
	// ... 
    function getRxInspector() {
        return {
            inputs: {
                rxData: {
					// ...
                    fieldId: {
                        label: 'Field Id',
                        type: 'com-example-samplelibrary-inspector-star-rating-field-select', // set our directive as editor
                        group: 'general',
                        index: 3
                    },
					stars: {
    					label: 'Stars',
    					type: 'number',		// set number as editor for stars
						min: 5, // minimal value
					    group: 'general',
    					index: 4
					}
                }
            }
        };
    }

    return {
        getModel: function (componentDefinition) {
            return new comExampleSamplelibraryStarRatingModel(getRxConfig(componentDefinition));
        }
    };
});

After you create the editor and redeploy the bundle, you can view that the Field ID property is displayed in the Properties pane as a dropdown.

Enhancing view component

To retrieve a record instance, the rxRecordInstanceResource service is used.

angular.module('com.example.samplelibrary.view-components.star-rating', [
    'com.bmc.arsys.rx.standardlib.view-component',
    'com.bmc.arsys.rx.standardlib.record.definition',
    'com.bmc.arsys.rx.standardlib.record.instance' // contains rxRecordInstanceResource resource
]);

The runtime directive gets access to configuration properties using the $scope.rxConfiguration.propertiesByName method.

star-rating.directive.js
angular.module('com.example.samplelibrary.view-components.star-rating').directive('comExampleSamplelibraryStarRating', function (rxRecordInstanceResource) {
    return {
        restrict: 'E',
        templateUrl: 'scripts/com.example.samplelibrary/view-components/star-rating/com-example-samplelibrary-star-rating.directive.html',

        scope: {
            rxConfiguration: '='
        },

        link: function ($scope, $element) {
            var config = $scope.rxConfiguration.propertiesByName;
            var recordInstanceResource = rxRecordInstanceResource.withName(config.recordDefinitionName);
            var recordInstance = null;

			$scope.stars = [];

            $scope.onStarSelectHandler = function (event) {
                var selectedIndex = _.indexOf($element.find('span'), event.target);

                if (selectedIndex !== -1) {
                    $scope.stars = buildStarsConfiguration(selectedIndex);

					// update rating value
                    recordInstance.setValue(config.fieldId, selectedIndex);
                    recordInstance.save();
                }
            };

            function initialize() {
                recordInstanceResource.get(config.recordInstanceId).then(function (_recordInstance) {
                    recordInstance = _recordInstance;

                    $scope.stars = buildStarsConfiguration(recordInstance.fieldInstances[config.fieldId].value || 0);
                }).catch(function () {
                    $scope.stars = [];
                });
            }

            function buildStarsConfiguration(starCount) {
                var stars = [];

                for (var i = 1; i <= config.stars; i++) {
                    stars[i] = {
                        icon: i <= starCount ? 'd-icon-star' : 'd-icon-star_o'
                    };
                }

                return stars;
            }

            initialize();
        }
    };
});

Sample directive template:

com-example-samplelibrary-star-rating.directive.html
<div ng-click="onStarSelectHandler($event)">
    <span ng-repeat="star in stars track by $index" class="{{star.icon}}"></span>
</div>

After you redeploy the bundle, the Start Rating view component is displayed as shown in the following image:

Interacting with other view components

View components can exchange data using expressions.

Receiving data from other components

After you configure a constant value for the Record Instance ID configuration property at design time, you can also update the Star Rating view component to use a dynamic value for the Record Instance ID configuration property. The following example shows how to retrive value from a record selected in the record grid view component.

  1. Mark the view component properties that can accept expressions with the enableExpressionEvaluation flag in the star-rating.config.js file.

    star-rating.config.js
    angular.module('com.example.samplelibrary.view-components.star-rating').config(function (rxViewComponentProvider) {
        var starRatingDescriptor = {
    		// ... 
    
            propertiesByName: [
                // ...
                {
                    name: 'recordInstanceId',
                    isRequired: true,
                    isConfig: true,
                    enableExpressionEvaluation: true //  the property will be automatically evaluated at runtime and passed to the runtime directive
                }
            ]
        };
    
        rxViewComponentProvider.registerComponent(starRatingDescriptor);
    });

    The property value is evaluated automatically during runtime and the actual value is passed to the view component runtime directive.

  2. Add a record grid view component to the canvas and bind it to the same record definition as the Star Rating view component and ensure that you set row selection to Single row.
  3. For recordInstanceId property, select Record Grid > Selected Rows > First Selected Row > ID expression.
  4. Implement a watcher on the recordInstanceId property in the star-rating.directive.js.
    When user selects a record instance in the grid, the Star Rating view component receives the ID of the selected record instance. To react to the record instance ID changes, you must implement a watcher.

    Sample code:

    star-rating.directive.js
    angular.module('com.example.samplelibrary.view-components.star-rating').directive('comExampleSamplelibraryStarRating', function (rxRecordInstanceResource) {
        return {
            restrict: 'E',
            templateUrl: 'scripts/com.example.samplelibrary/view-components/star-rating/com-example-samplelibrary-star-rating.directive.html',
    
            scope: {
                rxConfiguration: '='
            },
    
            link: function ($scope, $element) {
                var config = $scope.rxConfiguration.propertiesByName;
                var recordResource = rxRecordInstanceResource.withName(config.recordDefinitionName);
                var recordInstance = null;
    
                $scope.stars = [];
    
                $scope.onStarSelectHandler = function (event) {
                    var selectedIndex = _.indexOf($element.find('span'), event.target);
    
                    if (selectedIndex !== -1) {
                        $scope.stars = buildStarsConfiguration(selectedIndex);
    
                        recordInstance.fieldInstances[config.fieldId].value = selectedIndex;
                        recordInstance.save();
                    }
                };
    
                initialize();
    
                function initialize() {
    				// reinitialize configuration each time when recordInstanceId is changed
                    $scope.$watch('rxConfiguration.propertiesByName.recordInstanceId', initializeStars);
                }
    			
                function initializeStars() {
                    if (config.recordInstanceId) {
                        recordResource.get(config.recordInstanceId).then(function (recordInstanceResource) {
                            recordInstance = recordInstanceResource;
                            $scope.stars = buildStarsConfiguration(recordInstanceResource.fieldInstances[config.fieldId].value || 0);
                        }).catch(function () {
                            $scope.stars = [];
                        });
                    } else {
                        $scope.stars = [];
                    }
                }
    
                function buildStarsConfiguration(starCount) {
                    var stars = [];
    
                    for (var i = 1; i <= config.stars; i++) {
                        stars[i] = {
                            icon: i <= starCount ? 'd-icon-star' : 'd-icon-star_o'
                        };
                    }
    
                    return stars;
                }
            }
        };
    });

After you redeploy the bundle, the Star Rating view component reflects the rating from the record instance selected in the record grid.

Sharing data with the other view components

Consider that the other view components need the current rating value in the Star Rating view component. In this case, the Star Rating view component has to expose the its properties:

  1. During component registration, mark property as isProperty :

    star-rating.config.js
    angular.module('com.example.samplelibrary.view-components.star-rating').config(function (rxViewComponentProvider) {
        var starRatingDescriptor = {
            // ...
    
            propertiesByName: [
                {
                    name: 'stars',
                    isConfig: true,
                    isProperty: true,	 // property will be available for building expressions
                    defaultValue: 5
                }
            ]
        };
    
        rxViewComponentProvider.registerComponent(starRatingDescriptor);
    });

    This makes the Star Rating property available in the data dictionary at design time. It can be used in expressions for other view component properties.

  2. Notify the view about the changes to this property. When the stars property changes, the view component triggers a propertyChanged event. When the view catches this event, it evaluates all expressions that use the stars property and passes the updated value to other view components.

    Sample code in star-rating.directive.js file:

    star-rating.directive.js
    angular.module('com.example.samplelibrary.view-components.star-rating').directive('comExampleSamplelibraryStarRating', function (rxRecordInstanceResource, rxViewComponentEventManager) {
        return {
            restrict: 'E',
            templateUrl: 'scripts/com.example.samplelibrary/view-components/star-rating/com-example-samplelibrary-star-rating.directive.html',
    
            scope: {
                rxConfiguration: '='
            },
    
            link: function ($scope, $element) {
    			// ...
     
    			// create event manager
                var eventManager = rxViewComponentEventManager.getInstance($scope);
    
                $scope.stars = [];
    
                $scope.onStarSelectHandler = function (event) {
                    var selectedIndex = _.indexOf($element.find('span'), event.target);
    
                    if (selectedIndex !== -1) {
                        $scope.stars = buildStarsConfiguration(selectedIndex);
    
    					// trigger the change property event
                        eventManager.propertyChanged({
                            property: 'stars', // name of the property that changed
                            newValue: selectedIndex
                        });
    
                        recordInstance.setValue(config.fieldId, selectedIndex);
                        recordInstance.save();
                    }
                };
            }
        };
    });

Related topics

Creating custom view components 

Creating custom view components for record editor 

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

  1. Shanky Gupta

    If you are following Create Basic Components and want to deploy the star rating component for an application, then in the star-rating.config.js file change the group attribute value to 'Basic Components'. It should be put as shown below:

    group: 'Basic Components'

    Apr 29, 2019 07:35
  2. Shanky Gupta

    In the screenshots showing the star rating component in view designer, under each component Click to Build an expression feature is available in each of the 4 properties. In the code while defining propertiesByName enableExpressionEvaluation: true has to be added for all the properties to achieve it which is missing in the code above. Please see an example for the property which is actually used in the code above:

    { name: 'recordDefinitionName', isConfig: true, enableExpressionEvaluation: true, isRequired: true },

    Apr 30, 2019 03:53
    1. Aaditi Lakade

      Thanks, Shanky Gupta for the above comments. I have updated this topic according to your suggestions. Please confirm the changes for group: 'Basic Components' and enableExpressionEvaluation: true in the star-rating.config.js file.

      -Aaditi

      May 01, 2019 10:13