Czym są akcje zdarzeniowe
Akcje reagujące na zdarzenia (inaczej akcje zdarzeniowe) to rodzaj komponentów integracyjnych które uruchamiane są w odpowiedzi na wystąpienie dowolnego zdarzenia na formularzu zadania.
Zdarzenie
Istnieją dwa źródła zdarzeń:
- formularz zadań - tzw. zdarzenia systemowe (np. zmiana wartości zmiennej, kliknięcie w przycisk)
- akcje zdarzeniowe
Każde zdarzenie posiada nazwę oraz dowolną liczbę właściwości (properties) o zdefiniowanym typie. Twórca akcji może ze swojej akcji wywołać dowolne zdarzenie, na które można będzie uruchomić dowolną inną akcje. Takie rozwiązanie daje więcej elastyczności podczas tworzenia procesów w stosunku do tradycyjnych akcji formularza. Twórca akcji ma całkowitą kontrolę nad momentem i kolejnością wykonywania akcji.
Właściwości zdarzenia mogą być mapowane na parametry akcji w sposób analogiczny do "zmiennych kontekstowych" klasycznych akcji formularza.
Akcje zdarzeniowe a akcje formularza
Akcje formularza same definiują zdarzenia w odpowiedzi na które zostaną uruchomione. Taki sposób uruchamiania akcji sprawia że nie są one tak elastyczne (np. wykonanie akcji na innym zdarzeniu wymaga zmiany implementacji). W przypadku akcji zdarzeniowych, to twórca procesu decyduje kiedy dana akcja ma się wywołać i z jakimi parametrami.
Kolejność wykonywania akcji zdarzeniowych
Diagram przedstawia kolejność wykonywania akcji w reakcji na zdarzenie change. Wszystkie 3 akcje (Action1, Action2, Action3) zdefiniowane są następujący sposób (w podanej kolejności):
Zdarzenie | Akcje |
---|---|
change |
|
success (Action1) |
|
Akcje są wywoływane w kolejności zdefiniowanej na mapie procesu w głąb czyli najpierw wywołane będą akcje zależne od zdarzeń już wywołanych akcji, dopiero po zakończeniu tego łańcucha wywoływana jest następna akcja zdefiniowana dla zdarzenia źródłowego:
Akcje asynchroniczne
Szczególnym przypadkiem są akcje asynchroniczne czyli takie które przed zakończeniem wywołania wykonują dowolną asynchroniczną akcje (np. żądanie http). W takim przypadku wywoływane są wszystkie zdefiniowane akcje nawet jeżeli niektóre z nich przeszły w tryb asynchroniczny. Dopiero po zakończeniu wywłania asynchronicznego łąńcuch akcji jest wznawiany.
Zdarzenia systemowe
Spis zdarzeń formularza zadania dla których mogą zostać podpięte akcje zdarzeniowe.
Globalne
Zdarzenie | Opis | Parametry |
---|---|---|
afterLoadForm | Zdarzenie wywoływane po załadowaniu wszystkich komponentów formularza |
|
Zmienne procesu
Zmienna formularza, nie będąca częścią tabelki dynamicznej
Zdarzenie | Opis | Parametry |
---|---|---|
change | Zdarzenie wywoływane po zmianie wartości zmiennej |
|
focus | Zdarzenie wywoływane gdy pole otrzyma focus | |
blur | Zdarzenie wywoływane gdy pole straci focus | |
show | Zdarzenie wywoływane gdy pole zostanie odkryte | |
hide | Zdarzenie wywoływane gdy pole zostanie ukryte |
Tabelki
Zdarzenie | Opis | Parametry |
---|---|---|
select | Zdarzenie wywoływane po wybraniu wiersza w tabeli |
|
cellClick | Zdarzenie wywoływane po kliknięciu w komórkę tabeli |
|
afterAddRecords | Zdarzenie wywoływane po dodaniu rekordów do tabeli |
|
afterRemoveRecords | Zdarzenie wywoływane po usunięciu rekordów z tabeli |
|
afterAddRecords | Zdarzenie wywoływane po zmianie rekordów w tabeli |
|
afterRender | Zdarzenie wywołane po wyrenderowaniu tabeli | |
show | Zdarzenie wywołane po odkryciu tabeli | |
hide | Zdarzenie wywołane po ukryciu tabeli |
Przyciski
Przyciski dostępne na formularzu
Zdarzenie | Opis | Parametry |
---|---|---|
click | Zdarzenie wywoływane po kliknięciu przycisku |
|
disable | Zdarzenie wywoływane po zablokowaniu przycisku | |
enable | Zdarzenie wywoływane po odblokowaniu przycisku | |
show | Zdarzenie wywoływane po odkryciu przycisku | |
hide | Zdarzenie wywoływane po ukryciu przycisku |
Implementacja
W sposób analogiczny do klasycznych akcji formularza, akcje zdarzeniowe dostarczane są przez wtyczki.
suncode-plugin.xml musi zawierać deklaracje modułu workflow-components
< workflow-components key = "components" /> |
Definicja akcji
Definicja
@EventActions // oznaczenie komponentu zawierającego akcje zdarzeniowe @ActionsScript( "scripts/eventactions.js" ) // wskazuje skrypt z implementacją akcji public class SetVariables { @Define public void setVariables(EventActionDefinitionBuilder eventAction ) { //@formatter:off eventAction .id( "test-action" ) .name( "Test action" ) .description( "eventaction.test-action.desc" ) .icon( SilkIconPack.APPLICATION_FORM_EDIT ) .category( Categories.GENERAL ) .documentationLink( "link" ) .parameter() // deklaracja paremetrów które przyjmuje akcja .id( "param1" ) .name( "param1" ) .type( Types.STRING ) .create() .event("success") // deklaracja zdarzeń które mogą być wyzwolone przez akcje .description("") .property("foo") // właściwości zdarzeń .name("Foo") .description("Bar") .type(Types.BOOLEAN) ; //@formatter:on } }
Rejestracja implementacji akcji na formularzu
Rejestracja akcji odbywa się poprzez wywołanie
PW.EventActions.register(name, function)
gdzie:
name: nazwa rejestrowanej akcji - musi być zgodna z nazwą akcji z definicji komponentu
function(context, ...params): funkcja która zostanie wywołana w momencie wystąpienia zdarzenia, pod które została podpięta dana akcja, przyjmuje ona następujące parametry:
context: pierwszy parametr to kontekst formularza, służący do efektywnego ustawiania wartości wszystich zmiennych formularza
<params>: kolejne parametry to parametry wywołania akcji zgodnie z deklaracją, kolejność parametrów jest zgodna z kolejnością w deklaracji komponentu
PW.EventActions.register("test-action", function(context, param1) { if(param1 == 'foo') { this.fireEvent("success", {"foo": true}); } });
Kontekst formularza
Pierwszym parametrem każdej akcji jest context - kontekst formularza. Reprezentuje on aktualny stan formularza (wartości wszystkich zmiennych). Stan ten jest przekazywany do kolejnych akcji gdzie może być przez nie dowolnie modyfikowany. W momencie obsłużenia wszystkich akcji (w ramach jednego zdarzenia formularza), finalny stan porównywany jest z początkowym stanem formularza a wszystkie zmiany są na niego aplikowane.
Takie rozwiązanie powoduje że zmiana wartości zmiennych formularza w momencie przetwarzania akcji jest bardzo szyba, ponieważ zmiany te nie są propagowane na formularz w momencie dokonania, a dopiero w momencie gdy wszystkie akcje z tzw. łańcucha akcji zostaną obsłużone.
Zmiana wartości zmiennych
API reference: Akcje reagujące na zdarzenia
Zmiana zmiennych nagłówkowych:
PW.EventActions.register("test-action", function(context) { const value = context.variable("zmienna_1").get(); context.variable("zmienna_2").set("zmienna_1:" + value); });
Zmiana rekordów w tabeli:
PW.EventActions.register("test-action", function(context) { const table = context.variableSet("table_1"); table.variable("zmienna_1").add("new_value"); });
Akcje asynchroniczne
Akcje asynchroniczne to akcje w których zachodzi potrzeba wywołania asynchronicznego kodu (np. żądania http lub wyświetlenie modal'a z callbackiem). Aby taka akcja była w stanie zmieniać stan formularza i wyzwalać kolejne akcje w reakcji na zdarzenia wyemitowany poprzez this.fireEvent() niezbędne jest zwrócenie kontroli do framework'u akcji.
Służy do tego funkcja this.async(function) która przyjmuje funkcje callback'u jaki będzie wywołany po powrocie z asynchronicznego wywołania oraz zwraca tą samą funkcję wzbogaconą o logikę wznowienia wykonywania akcji.
Przed wywołaniem funkcji przekazanej przez twórcę do funkcji async() system wczyta aktualny kontekst formularza i wznowi wykonywanie łańcucha akcji, a po zakończeniu naniesie zmiany na formularz zadania.
Przykład poprawnej i błędnej implementacji akcji asynchronicznej:
PW.EventActions.register("async-action", function(context) { context.set("var1", "before"); // zmiana kontekstu jest dozwolona przed przejściem w tryb asynchroniczny this.fireEvent("before_async"); // tak samo jak wyzwalanie zdarzeń // wywołanie asynchroniczne (np. odpowiedź serwera, modala) // funkcje przekazywaną jako callback należy wcześniej przygotować używając funkcji this.async() setTimeout(this.async(() => { context.set("var1", "after"); this.fireEvent("after_async"); }), 1000); // w przypadku gdy nie użyjemy funkcji this.async() - dostęp do kontekstu bądź i wyzwalanie zdarzeń nie jest możliwe i zakończy się błędem setTimeout(() => { this.fireEvent("will throw"); }, 1000); });
Context API
Context | |
---|---|
Funkcja | Opis |
variable(id) : VariableContext | Zwraca VariableContext zmiennej o podanym identyfikatorze |
variableSet(tableId) : VariableSetContext | Zwraca VariableSetContext tabeli o podanym identyfikatorze |
VariableContext | |
---|---|
Funkcja | Opis |
set(newValue): this | Zmiana wartości zmiennej |
get(): Object | Zwraca aktualną wartość zmiennej |
VariableSetContext | |
---|---|
Funkcja | Opis |
variable(id).add(newValue): this
| Dodanie nowej wartości (wiersza) |
variable(id).set(newValues): this | Zmiana wartości zmiennej w tabeli |
variable(id).get(): Object[] | Zwraca aktualną wartość zmiennej (tablica) |
addRecords(tableStore): this | Dodaje rekordy opisane podanym TableStore'em |
Troubleshooting
Logowanie wywołania akcji
Jeżeli potrzebujemy więcej informacji o wykonywanych akcjach, ich parametrach lub właściwościach zdarzeń możemy włączyć dokładne logowanie na poziomie Trace. W tym celu należy:
- uruchomić formularz w trybie devMode (poprzez dodanie na końcu adresu URL &devMode=true)
- upewnić się że konsola wyświetla wiadomości na poziomie Trace/Verbose ( w Google Chrome poziom Verbose jest domyślnie wyłączony)
EventActions chain started: {name: 'afterLoadForm', props: constructor} Context {state: {…}} EventActions: invoking action: tr {action: {…}, on: {…}} on event: {name: 'afterLoadForm', props: constructor} Context {state: {…}} EventActions chain finished: {name: 'afterLoadForm', props: constructor} Context {state: {…}}
Znane błędy
EventAction: No active context found: most likely this code was invoked asynchronously, did you forgot 'this.async()'?
Błąd oznacza próbę interakcji z akcją, jej context'em lub parametrami po wykonaniu akcji bądź w przypadku akcji asynchronicznych, bez wcześniejszego użycia funkcji this.async(). Patrz Akcje asynchroniczne