External WebComponent

The availability of features depends on the license and may not be available in all deployments.

ExternalWebComponent is a specialized component that allows creating controls outside the set available on the palette. You only need to write your own WebComponent using HTML and JavaScript and return a reference to the file with that content via a service (ScriptService or ServiceProxy).

Component input parameters

Parameter
Description

componentUrl

full link to the WebComponent source

tag

the tag by which it should identify itself

inputs

list of input parameters for the Component as JSON

List of input model parameters for the WebComponent

Input parameter
Possible value
Description

name

*

Parameter name

value

*

Constant value or the name of the component on the application

type

CONSTANT / FIELD

Type of the passed value

deliveryType

ATTRIBUTE / PROPERTY

Method of delivering the value to the WebComponent

Communication

  • All parameters to the component (defined in the designer) are passed to the component via attributes. If we receive a new value from the server, the attribute value will be changed.

  • In the case of empty values, attributes will not be created.

  • If an update of the value clears the value of a given attribute, the platform will remove that attribute from the element.

  • The component may use any methods exposed by the eximee API on the window object

    export interface ExWebformsWindow extends Window {
        getComponentValue: (componentId: string) => unknown;
        setComponentValue: (sourceComponentId: string, componentId: string, newValue: string) => unknown;
        updateExternalSectionValue: (externalSectionId: string, newValue: string) => unknown;
        finishApplication: () => void;
        applicationSetTitle: () => void;
        goForward: () => void;
        goBackward: () => void;
        returnToOriginalForm: () => boolean;
    }
  • The component can change its own value by emitting an event change with the field details containing an object that satisfies the interface { value: string }. This can be achieved, for example, by creating an object of type CustomEvent (e.g.: new CustomEvent('change', {detail: {value: event.target.value}})). Additionally, the component may emit events focus and blur - they will not affect the application logic, but will be recorded in statistics. WARNING! Code should respect the fact of the component being removed from the DOM - any events sent after the component is removed may prevent submitting the application.

  • Besides the defined attributes, the platform will set the following attributes on the component:

    • id - the element identifier in the DOM structure. The platform ensures its uniqueness and compliance with the HTML specification

    • component-id - the component identifier - this identifier should be used when communicating with the platform

    • value - the current value of the component

    • translations - JSON with translations (key-value) for literals in the webcomponent

  • An attribute may be set by the platform after connectedCallback - you need to hook into attributeChangedCallback

Configuration

A constant configuration may look as follows:

<p1:GesExternalWebComponent id="GesExternalWebComponent2" mid="GesExternalWebComponent2" inheritLayout="false" tag="img-only" componentUrl="https://dev.bank.eximee.consdata.local/bank-demo-ewc/imgonly.js">
  <data:ListeningOn/>
  <data:ClearOn/>
  <p1:GesExternalWebComponent.layoutData>
    <ns6:GridData horizontalAlignment="FILL" horizontalSpan="17" verticalAlignment="CENTER"/>
  </p1:GesExternalWebComponent.layoutData>
  <data:ExternalWebComponentInputMapping>
    <data:ExternalWebComponentMapping value="some-value" name="name1" type="CONSTANT" deliveryType="ATTRIBUTE"/>
    <data:ExternalWebComponentMapping value="GesTextField1" name="name2" type="FIELD" deliveryType="PROPERTY"/>
  </data:ExternalWebComponentInputMapping>
</p1:GesExternalWebComponent>

You can also attach a ServiceProxy (ScriptService) that will return the above data.

<p1:GesExternalWebComponent id="GesExternalWebComponent1" mid="GesExternalWebComponent1" inheritLayout="false">
  <data:ExternalDataSource name="demo_cross_sell_ewc" type="SCRIPT_SERVICE" changesWidgetAttributes="false" version="*">
    <data:OutputFields>
      <data:Field localName="componentUrl" serviceName="url_to_webcomponent"/>
      <data:Field localName="tag" serviceName="webcomponent_tag"/>
    </data:OutputFields>
  </data:ExternalDataSource>
  <data:ListeningOn/>
  <data:ClearOn/>
  <p1:GesExternalWebComponent.layoutData>
    <ns6:GridData horizontalAlignment="FILL" horizontalSpan="17" verticalAlignment="CENTER"/>
  </p1:GesExternalWebComponent.layoutData>
</p1:GesExternalWebComponent>

Example WebComponent

const imgTemplate = document.createElement('template');
imgTemplate.innerHTML = `
    <div class="wrapper">
        <img id="noAttributeAndProperty" src="https://prowly-uploads.s3.eu-west-1.amazonaws.com/uploads/4843/assets/191020/large-09ba51481c9c5dd157eea3438af2bcbf.png" width="300" height="350"/>
        <img id="falseAtribute" style="display: none" src="https://upload.wikimedia.org/wikipedia/en/1/14/WO%C5%9AP.svg" width="300" height="350"/>
        <img id="trueAtribute" style="display: none" src="https://www.wroclaw.pl/go/download/img-32cf4a052df7bd08570783a8351863eb/wosp-26-jpg.jpg" width="300" height="350"/>
        <img id="falseProperty" style="display: none" src="https://static.wosp.org.pl/trunk/uploaded/sended/files/programy/logo-rur-pl.png?1573732254027" width="300" height="350"/>
        <img id="trueProperty" style="display: none" src="https://admonkey.pl/wp-content/uploads/2017/01/logo_wosp.jpg" width="300" height="350"/>
    </div>`;
 
 
class ImgOnly extends HTMLElement {
 
    constructor() {
        super();
        this.shadow = this.attachShadow({
            mode: 'open'
        });
    }
 
    getAtributesAndProperties() {
        let atrGroup = null
        let propsGroup = null
        let element = document.getElementById('GesComplexComponent1_GesExternalWebComponent2-element')
        if (!!element) {
            atrGroup = element.getAttribute("atrgroup")
            propsGroup = element['propsGroup']
        }
        if ((atrGroup == null || atrGroup == undefined) && (propsGroup == null || propsGroup == undefined)) {
            this.shadow.getElementById("noAttributeAndProperty").style.display = "inline-block";
            return;
        } else {
            element.shadowRoot.getElementById("noAttributeAndProperty").style.display = "none";
        }
        if (atrGroup === "true") {
            element.shadowRoot.getElementById("trueAtribute").style.display = "inline-block";
            element.shadowRoot.getElementById("falseAtribute").style.display = "none";
        }
        if (atrGroup === "false") {
            element.shadowRoot.getElementById("falseAtribute").style.display = "inline-block";
            element.shadowRoot.getElementById("trueAtribute").style.display = "none";
        }
        if (propsGroup === "true") {
            element.shadowRoot.getElementById("trueProperty").style.display = "inline-block";
            element.shadowRoot.getElementById("falseProperty").style.display = "none";
        }
        if (propsGroup === "false") {
            element.shadowRoot.getElementById("falseProperty").style.display = "inline-block";
            element.shadowRoot.getElementById("trueProperty").style.display = "none";
        }
 
    }
 
    connectedCallback() {
        this.shadow.appendChild(imgTemplate.content.cloneNode(true));
        setInterval(this.getAtributesAndProperties, 500);
 
    }
 
    attributeChangedCallback(name, oldValue, newValue) {
        switch (name) {
            case 'atrgroup':
                this.getAtributesAndProperties();
                break;
        }
    }
 
 
    static get observedAttributes() {
        return ['atrgroup'];
    }
}
 
window.customElements.define('img-only', ImgOnly);

Last updated

Was this helpful?