Komponent niestandardowy - CustomComponent

Komponent niestandardowy (CustomComponent) pozwala na tworzenie własnych komponentów dla wniosku z wykorzystaniem języka JavaScript.

CustomComponent składa się z ośmiu elementów:

  • Skryptu JavaScript,

  • Stylów CSS komponentu,

  • Szablonu HTML komponentu,

  • Mapowań parametrów wejściowych komponentu,

  • Listy użytych serwisów,

  • Listy akcji dostępnych dla tego komponentu,

  • Tłumaczeń tekstów dla komponentu,

  • Podglądu.

Tworzenie komponentu

Nowy komponent tworzy się w ten sam sposób co inne komponenty. Po przejściu do modułu Biblioteka i wybraniu zakładki Komponenty niestandardowe klikamy przycisk Dodaj komponent niestandardowy i w otwartym oknie ustalamy nazwę i lokalizację tworzonego artefaktu (Więcej informacji na temat samego edytora: Edytor komponentów niestandardowych)

Ilustracja 1. Widok edycji nowo utworzonego komponentu

Skrypt JavaScript

Każdy z CustomComponent'ów składa się z jednej głównej funkcji, której przekazywany jest Scope komponentu:

function($scope) {
  
}

Za pomocą scopu twórca może m.in. pobierać dane komponentu, dane wejściowe oraz reagować na pewne zdarzenia z cyklu życia komponentu. Użytkownik może zaimplementować trzy systemowe metody komponentu:

  • afterViewInit - wykonywana w momencie dodania komponentu do struktury DOM wniosku,

  • onModelChange - wykonywana w momencie zmiany modelu (np. wartości) komponentu lub wartosci danych wejściowych,

  • onDestroy - wykonywana w momencie usuwania komponentu ze struktury DOM wniosku.

Dodatkowo scope komponentu dostarcza kilka przydatnych elementów:

  • pola:

    • domId - ID komponentu w strukturze DOM wniosku

    • componentId - ID komponentu

    • componentMid - MID komponentu

    • visible - zmienna sterująca widocznością komponentu

    • translations - mapa tłumaczeń zdefiniowanych na etapie tworzenia komponentu

    • componentId - mapa parametrów wejściowych komponentów

    • componentData - mapa wewnętrznych danych komponentu (pozwala na zachowanie stanu komponentu)

    • componentInput - mapa danych wejściowych komponentu (klucze definiowane są w sekcji Inputs oddzielone przecinkami)

  • metody:

    • getValue() - pobiera aktualną wartość komponentu

    • setValue(value) - ustawia aktualna wartość komponentu

    • querySelector(query) - zwraca element struktury DOM komponentu, który został dopasowany do selektora.

    • putData(key, value) - ustawia określoną wartość (value) pod kluczem (key) w mapie danych komponentu - tylko po stronie klienta przeglądarki

    • saveData(key, value) - ustawia określoną wartość (value) pod kluczem (key) w mapie danych komponentu - także po stronie serwera

    • getData(key) - pobiera wartość określoną pod kluczem (key) w mapie danych komponentu

    • translate(key) - zwraca tłumaczenie z mapy tłumaczeń

    • clean() - czyści obiekt scope, gdy nie jest już używany przez CustomComponent

    • callServiceProxy(serviceName, params) - pozwala zawołać usługi ServiceProxy oraz ScriptService w sposób synchroniczny

    • callServiceProxyAsync(serviceName, params) - pozwala zawołać usługi ServiceProxy oraz ScriptService w sposób asynchroniczny

    • initTooltip(id, element, data) - pozwala zainicjować tooltip o zadanym identyfikatorze (wartość wymagana, musi spełniać wszystkie założenia atrybutu ID w języku HTML) na przekazanym elemencie

    • showTooltip(id) - pokazuje tooltip o zadanym id

    • hideTooltip(id) - ukrywa tooltip o zadanym id

    • destroyTooltip(id) - niszczy tooltip o zadanym id

    • destroyAllTooltips() - niszczy wszystkie tooltipy danego komponentu

    • goForward() - nawiguje do następnej (dozwolonej) strony lub wysyła wniosek (gdy użytkownik znajduje się na ostatniej stronie wniosku)

    • goBackward() - nawiguje do poprzedniej (dozwolonej) strony

    • setInactiveForward() - ustawia przycisk nawigujący do następnej strony na zablokowany (Dostępność funkcjonalności zależy od licencji i może nie być dostępna we wszystkich wdrożeniach.)

    • setActiveForward() - ustawia przycisk nawigujący do następnej strony na aktywny (Dostępność funkcjonalności zależy od licencji i może nie być dostępna we wszystkich wdrożeniach.)

    • triggerCustomEvent(eventName) - pozwala wywołać CustomEvent zdefiniowany wcześniej dla danego komponentu

    • sendCurrentValueEvent() - wysyła event zawierający aktualną wartość CustomComponentu wraz z jego id

    • isPageValid() - zwraca informację czy na stronie są błędy walidacji

Interfejsy komponentu

interface ExCustomComponentScope {
    // Metody, które można dostarczyć
    onDestroy?: () => void;
    afterViewInit?: () => void;
    onModelChange?: () => void;
    onMessagesUpdate?: (messages: ExWidgetMessage[]) => void;
 
    // Pola dostarczane przez platformę
    domId: string;
    componentId: string;
    componentMid: string;
    translations: { [key: string]: string; };
    componentInput: { [key: string]: string[]; };
    componentData: { [key: string]: string; };
    serviceResponses: { [key: string]: { [key: string]: string }[] };
    visible: boolean;
 
    // Metody dostarczane przez platformę - nie należy ich nadpisywać
    callNative(nativeFunction: (api: NativeAppApi) => any): void
    getValue(): string;
    setValue(value: string): void;
    /**
     * @deprecated Nowe CustomComponenty powinny korzystać z querySelector
    */
    queryChild(query: string): JQuery;
    querySelector(query: string): Element;
    putData(key: string, value: string): void;
    saveData(key: string, value: string): void;
    getData(key: string): string;
    translate(key: string): string;
    schedule(func: () => any): void;
    clean(): void;
    callServiceProxy(serviceName: string, params: { [key: string]: string[] }): Observable<ExServiceProxyResponse>;
    callServiceProxyAsync(serviceName: string, params: { [key: string]: string[] }): Observable<ExServiceProxyResponse>;
    initTooltip(id: string, element: any, data: ExWidgetTooltip): void;
    destroyTooltip(id: string): void;
    showTooltip(id: string): void;
    hideTooltip(id: string): void;
    destroyAllTooltips(): void;
    goForward(): void;
    goBackward(): void;
    setActiveForward(): void;
    setInactiveForward(): void;
    triggerCustomEvent(event: string): void;
    sendCurrentValueEvent(): void;
    isPageValid(): Observable<boolean>;
}
 
interface ExServiceProxyResponse {
    name: string;
    componentId: string;
    response: { [key: string]: string }[];
}
 
interface ExWidgetTooltip {
    text: string;
    position: ExWidgetTooltipPosition;
    type: ExWidgetTooltipType;
    width?: number;
    height?: number;
    styleClasses?: string;
    onFocus?: boolean;
}
 
enum ExWidgetTooltipPosition {
    TOP,
    BOTTOM,
    LEFT,
    RIGHT,
    ADAPTIVE,
// Depreacted:
    LEFT_TOP,
    LEFT_BOTTOM,
    RIGHT_TOP,
    RIGHT_BOTTOM
}
 
enum ExWidgetTooltipType {
    HOVER,
    BUTTON
}
interface ExWidgetMessage {
    getMessage(): string;
    getType(): ExWidgetMessageType;
}
 
enum ExWidgetMessageType {
    VALIDATION_POPUP,
    VALIDATION,
    INFO,
    COMPONENT_INFO
}

Przykład funkcji komponentu

function($scope) {
      $scope.closePopup = function() {
        $scope.queryChild('.kg-positive-decision-popup-wrapper').fadeOut(200);
        $scope.saveData('visible', 'false');
      };
      $scope.afterViewInit = function() {
        var visible = $scope.getData('visible');
        if(visible === 'false') {
          $scope.queryChild('.kg-positive-decision-popup-wrapper').hide();
        } else {
          $scope.closeButton = $scope.queryChild('.kg-positive-decision-popup-close-button');
          $scope.closeButton.on('click', $scope.closePopup);
          $scope.nextButton = $scope.queryChild('.kg-positive-decision-popup-next-button');
          $scope.nextButton.on('click', $scope.closePopup)
        }
      };
    }

W powyższym przykładzie zdefiniowany został komponent prezentujący na wniosku Popup z informacją o pozytywnej decyzji kredytowej:

Ilustracja 2. Popup zaprojektowany za pomocą CustomComponentu

W linii 6 zdefiniowana została systemowa funkcja afterViewInit inicjalizująca przyciski X oraz DALEJ, a także sterująca widocznością okna. W linii 2 zdefiniowano funkcją wykonywaną w momencie kliknięcia jednego z dwóch przycisków.

Struktura dom popupu:

<div class='kg-positive-decision-popup-wrapper'>
  <div class='kg-positive-decision-popup'>
    <div class='kg-positive-decision-popup-title-wrapper'>
        <div class='kg-positive-decision-popup-title'>
            _{kg.positive.decision.popup.title}
        </div>
        <button class='kg-positive-decision-popup-close-button'></button>
        <div class='clear'></div>
    </div>
    <div class='kg-positive-decision-popup-content-wrapper'>
        <div class='kg-positive-decision-popup-content-first-paragraph'>
            _{kg.positive.decision.popup.content.first.paragraph}
        </div>
        <div class='kg-positive-decision-popup-content-second-paragraph'>
            _{kg.positive.decision.popup.content.second.paragraph}
        </div>
    </div>
    <div class='kg-positive-decision-popup-next-button-wrapper'>
        <button class='kg-positive-decision-popup-next-button'>_{kg.positive.decision.popup.next.button}</button>
        <div class='clear'></div>
    </div>
  </div>
</div>

W definicji szablonu komponentu można odwoływać się do zdefiniowanych tłumaczeń stosując konwencję _{KLUCZ_TŁUMACZENIA} - przykład w linii 5.

Wywołanie skryptów lub ServiceProxy

Z poziomu CustomComponentu można zawołać usługi ServiceProxy oraz ScriptService korzystając z metod callServiceProxy oraz callServiceProxyAsync. Obie metody zwracają Observable z response o następującym formacie:

{
    name: string;
    componentId: string;
    response: { [key: string]: string }[];
}

Aby uzyskać response należy wywołać metodę .subscribe() znaną z RxJS. Podobnie jak ma to miejsce w RxJS warto także wywołać unsubscribe() w odpowiednim momencie na tak zwróconym obiekcie. Dla przykładu unsubscribe może zostać wywołany w metodzie onDestroy.

W przypadku użycia ServiceProxy lub ScriptService należy go dodać do listy używanych serwisów na CustomComponent:

Ilustracja 3. Sekcja "Wykorzystywane serwisy"

Pola wejściowe komponentu

W sekcji Dane wejściowe definiowane są id pól wejściowych komponentu. Id nie powinny zawierać spacji.

Ilustracja 4. Sekcja "Dane wejściowe"

Zdefiniowane pola wejściowe można zasilać innymi komponentami wniosku w identyczny sposób jak komponenty złożone (ComplexComponent) - mapując odpowiednie dane w sekcji PARAMETRY WEJŚCIOWE:

Ilustracja 5. Przykład sekcji "Parametry wejściowe" dla CustomComponentu dodanego na wniosku

Tłumaczenia

Dedykowane internacjonalizowane teksty definiowane są w sekcji Tłumaczenia komponentu, która wyświetla się po wybraniu w lewym panelu przycisku Tłumaczenia.

Ilustracja 6a. Sekcja "Tłumaczenia komponentu"

W widoku tym definiowany jest klucz oraz wartość domyślna tekstu obsługiwanego na CustomComponencie. Tłumaczenia tekstu w wymaganych językach definiowane są w sposób standardowy na wniosku, na którym komponent został podpięty.

Przykład dodawania klucza tłumaczeń:

  1. Po kliknięciu u dołu panelu przycisku Dodaj tłumaczenie należy dodać klucz tłumaczeń i wartość domyślną:

    Ilustracja 6b. Dodawanie nowego klucza i tłumaczenia
  2. Dodany klucz tłumaczeń możemy wykorzystać w strukturze DOM CustomComponentu:

    Ilustracja 6c. Sekcja "DOM" z wprowadzonym przykładowym kluczem "kg-final-survey-popup-title"

  3. Po dodaniu CustomComponent'u na wniosek lub do komponentu złożonego w zakładce Tłumaczenia pojawią się klucze z CustomComponentu. Możemy je także dodać ręcznie.

    Ilustracja 6d. Zakładka "Tłumaczenia" z kluczami CustomComponentu

Przejmowanie komunikatów

Aby CustomComponent sam obsługiwał komunikaty walidacyjne, należy w sekcji parametrów zaznaczyć opcję Niestandardowe prezentowanie komunikatu błędu. Opcja ta zezwala na obsługę wiadomości poprzez metodę onMessagesUpdate.

Ilustracja 7. Włączona opcja "Niestandardowe prezentowanie komunikatu błędu"

Definicja customowych eventów dla komponentu

Dla każdego CustomComponent można zdefiniować indywidualne akcje (CustomEvents). Podpinane i obsługiwane są w ten sam sposób co standardowe eventy definiowane w platformie. Definicja akcji wygląda następująco:

Ilustracja 8. Akcje dodane dla komponentu

Tak zdefiniowane akcje możemy podpiąć na wniosku do danej akcji. Przykładowo akcja TEST_EVENT_A służy do otwarcia popupa:

Ilustracja 9. Widok właściwości wniosku - sekcja "Akcje" ze zdefiniowaną akcją z CustomComponentu

Sam event możemy wywołać wewnątrz skryptu JS customComponentu, korzystając z metody triggerCustomEvent, na przykład:

$scope.triggerCustomEvent('TEST_EVENT_A');

Symulacja komponentu

Do sprawdzenia działania utworzonego CustomComponentu można wykorzystać funkcję symulacji. W tym celu klikamy znajdujący się w prawej części ekranu przycisk Podgląd. Jego kliknięcie zmienia wygląd ekranu w symulacyjny. Po lewej stronie zobaczymy okienka JavaScript, CSS i HTML, a po prawej parametry komponentu (pod warunkiem, że zostały zdefiniowane parametry wejściowe). Po uruchomieniu podglądu możemy zasilić komponent zmiennymi pobieranymi w komponencie i zaobserwować jego działanie bez konieczności osadzania na wniosku i uruchamiania na środowisku deweloperskim.

Ilustracja 10. Widok komponentu z włączonym podglądem, bez wypełnienia parametrów wejściowych

Jeśli chcemy aby zmiany w podglądzie pokazywały się na bieżąco, przed uzupełnieniem wartości pól parametrów komponentu warto zaznaczyć opcję Automatyczne odświeżanie. Po uzupełnieniu wszystkich pól klikamy przycisk Odśwież. Wówczas chowają się pola z wpisanymi wartościami, a pokazuje się wygląd komponentu. Zawsze można wyświetlić uzupełniane parametry, klikając opcję z liczbą parametrów i napisem (pokaż).

Ilustracja 11. Widok komponentu z symulacją

Po ponownym kliknięciu przycisku Podgląd wrócimy do standardowego widoku komponentu z listą parametrów po lewej stronie.

Osadzanie na wniosku

Stworzony CustomComponent osadzany jest na wniosku/w komponencie złożonym poprzez dodanie go z palety komponentów. W tym celu w lewym bocznym panelu klikamy na przycisk Dodaj komponent i w wysuniętym panelu komponentów wybieramy zakładkę Niestandardowe, która dostępna jest po kliknięciu symbolu . Zostanie wyświetlona lista dostępnych w repozytorium CustomComponentów. W górnej części panelu dostępne jest pole wyszukiwania umożliwiające szybsze znalezienie szukanego do osadzenia artefaktu. Dodanie komponentu polega na przeciągnięciu go z palety i upuszczeniu w odpowiednim miejscu na wniosku.

Ilustracja 12. Lista komponentów po kliknięciu zakładki Niestandardowe

Po osadzeniu komponentu na wniosku należy zasilić pola wejściowe komponentu (zdefiniowane zgodnie z sekcją Pola wejściowe komponentu) klikając w sekcji Podstawowe właściwości opcję PARAMETRY WEJŚCIOWE:

Ilustracja 13. Okno definiowania parametrów wejściowych CustomComponentu

Sterowanie aktywnością przycisku nawigującego do następnej strony

W zakladce JavaScript edytowanego CustomComponentu możemy skorzystać z metod:

  • setInactiveForward() - ustawia przycisk nawigujący do następnej strony na zablokowany

  • setActiveForward() - ustawia przycisk nawigujący do następnej strony na aktywny

Należy pamiętać, że wywołanie metody setInactiveForward wewnątrz afterViewInit spowoduje zablokowanie przycisku po każdej zmianie widoczności komponentu - należy zatem uwzględnić to w implementacji.

Sterowanie aktywnością przycisku można uzależnić od kanału w jakim wyświetlany jest wniosek za pomocą instrukcji warunkowej if , uwzględniającej zmienne sesyjne channel i channelDescritpion (należy pamiętać o ich wcześniejszym zmapowaniu do komponentu).

Wołanie native API

Obiekt $scope udostępnia funkcję callNative, która przyjmuje funkcję w której parametrem jest obiekt native API (sygnatura: callNative(nativeFunction: (api: NativeAppApi) => any): void). Obiekt api ma zdefiniowany interfejs dostarczany przez platformę eximee. Funkcja żądana na obiekcie native zostanie wywołana tylko jeśli w kontekście ten obiekt jest dostępny.

function($scope) {
    $scope.afterViewInit = function() {
        $scope.callNative(nativeApi => nativeApi.setTitle('tytuł'));
    }
}

Dostępność funkcjonalności zależy od licencji i może nie być dostępna we wszystkich wdrożeniach.

Sterowanie loaderem platformowym

Na obiekcie window dostępne są metody umożliwiające sterowanie loaderem platformowym:

  • startSpinner() - włącza loader

  • stopSpinner() - wyłącza loader

Last updated

Was this helpful?