# Język wyrażeń

**Język wyrażeń warunkowych w Eximee** pozwala definiować logikę warunkową (np. widoczność, aktywność, wymagalność pól) za pomocą składni JavaScript rozszerzonej o określone metody. Warunki są zapisywane jako wyrażenia, które platforma **Eximee** sprawdza w trakcie działania aplikacji. Poniżej opisano składnię, dostępne metody i atrybuty, a także narzędzia ułatwiające tworzenie i testowanie warunków.

## Wyrażenia warunkowe w Eximee

* **JavaScript w warunkach:** Wszystkie warunki w szablonie wniosku można opisać wyrażeniami języka JavaScript. Oznacza to, że w polu warunku możemy używać standardowych operatorów (`==`, `!=`, `>`, `<`, `&&`, `||`, `!`) oraz funkcji JavaScript. Składnia pozwala definiować m.in. negację (`!warunek`), koniunkcję (`warunek1 && warunek2`) oraz alternatywę warunków (`warunek1 || warunek2`).
* **Dostęp do wartości komponentów:** Do pobierania aktualnych wartości pól należy używać funkcji **`getValue("ID_KOMPONENTU")`**, gdzie *ID\_KOMPONENTU* to identyfikator pola, zmiennej sesyjnej lub komponentu w formularzu. [Jest to zalecany sposób uzyskania wartości komponentu (inne metody mogą powodować problemy z wydajnością). ](#user-content-fn-1)[^1]Przykładowo wywołanie `getValue("PoleTekst1")` zwróci bieżący tekst wpisany w polu tekstowym o ID = PoleTekst1.
* **Dostęp do innych atrybutów:** Poza wartością, komponenty posiadają też inne właściwości, do których można się odwołać. Służy do tego funkcja **`getData("ID_KOMPONENTU", "ATRYBUT")`**, zwracająca wartość zadanego atrybutu komponentu. Na przykład `getData("Checkbox1", "visible")` zwróci informację o widoczności pola **Checkbox1** (analogicznie do użycia `isVisible("Checkbox1")`). Lista dostępnych atrybutów dla poszczególnych typów komponentów jest przedstawiona w dokumentacji komponentów i częściowo omówiona w dalszej sekcji.
* **Typy danych w warunkach:** Wszystkie wartości pobrane z pól są traktowane jako tekst (łańcuch znaków) w momencie obliczania warunku. Dlatego przy porównaniach liczbowych lub logicznych należy samodzielnie konwertować typy danych. Można korzystać ze standardowych funkcji JavaScript, takich jak `parseInt()` (konwersja na liczbę całkowitą) czy `parseFloat()` (konwersja na liczbę zmiennoprzecinkową). Dla wartości logicznych warto pamiętać, że string `"true"`/`"false"` należy porównać jako ciąg znaków lub konwertować na typ boolean.
* **Stałe:** W wyrażeniach można używać stałych tekstowych (ujmowanych w cudzysłów), liczbowych (pisanych wprost) oraz logicznych (`true`/`false` bez cudzysłowu).
* **Zmienne sesyjne w warunkach:** Jeżeli chcemy użyć w warunku zmiennej sesyjnej (globalnej dla wniosku), możemy odwołać się do niej przez `getValue("NAZWA_ZMIENNEJ")`. W niektórych przypadkach (np. wewnątrz komponentów złożonych) należy poprzedzić nazwę zmiennej znakiem `@`. Przykładowo, wyrażenie `getValue("@zmienna1")=="Y"` sprawdzi, czy zmienna sesyjna `zmienna1` ma wartość "Y". Uwaga: Predefiniowane zmienne systemowe (jeśli występują) mogą nie wymagać tego prefixu. Zaleca się jednak stosowanie `@` przed nazwami własnych zmiennych w złożonych kontekstach, aby uniknąć niejednoznaczności.
* **Warunki złożone i zależności:** Można budować złożone wyrażenia, łącząc kilka porównań logicznymi operatorami. Np. wyrażenie `getValue("Pole1") != "" && parseInt(getValue("Pole2")) > 100.` Wyrażenie zwróci `true` tylko wtedy, gdy *Pole1* nie jest puste **i jednocześnie** wartość liczbowa *Pola2* jest większa od 100. W definiowaniu warunków, które zależą od wartości innych pól, **należy pamiętać o zdefiniowaniu nasłuchiwania** – więcej na ten temat w dalszej części (mechanizm [**ListeningOn**](#user-content-fn-2)[^2]).

## Atrybuty komponentów

Każdy komponent formularza posiada zestaw standardowych atrybutów opisujących jego stan. Najważniejsze wspólne atrybuty to:

* **`value`** – bieżąca *wewnętrzna* wartość komponentu (np. tekst wpisany w pole, zaznaczenie checkboxa, wybrana opcja listy).
* **`displayValue`** – wartość *wyświetlana* użytkownikowi. Często pokrywa się z `value`, ale dla niektórych pól może się różnić (np. w Comboboxie `value` to kod/ID wybranej opcji, a `displayValue` to tekst etykiety).
* **`visible`** – informacja o widoczności komponentu (`"true"` lub `"false"`). W warunkach można też użyć funkcji `isVisible("ID")` pełniącej podobną rolę.
* **`enabled`** – informacja o aktywności (edytowalności) komponentu, przyjmuje wartość `"true"` gdy pole jest aktywne lub `"false"` gdy jest wyłączone (nieedytowalne). Ten atrybut decyduje o tym, czy użytkownik może wchodzić w interakcje z danym polem.

Inne atrybuty mogą być specyficzne dla typu komponentu. Np. komponent listy rozwijanej (Combobox) udostępnia atrybuty **`label`** (tekst wybranej opcji), **`description`** (dodatkowy opis) czy **`size`** (liczba dostępnych opcji). Komponent *Oświadczenia* posiada kolekcję pozycji `statementsItemControl` reprezentujących poszczególne oświadczenia. Szczegółowy wykaz atrybutów znajduje się w dokumentacji każdego rodzaju komponentu.

|                                         |                                                                                                                        |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Pole tekstowe                           | <p>value<br>displayValue<br>visible</p>                                                                                |
| Obszar tekstu                           | <p>value<br>displayValue<br>visible</p>                                                                                |
| Data                                    | <p>value<br>displayValue<br>visible</p>                                                                                |
| Zakres dat                              | <p>value<br>displayValue<br>visible</p>                                                                                |
| Plus minus                              | <p>value<br>displayValue<br>visible</p>                                                                                |
| Treść formatowana (i zwijana)           | <p>value<br>displayValue<br>visible</p>                                                                                |
| Pole wyboru wartości z listy (Combobox) | <p>label - tekst wybranej wartości<br>description - description wybranej wartości<br>size - długość listy wartości</p> |
| Wybór rachunku                          | <p>value<br>displayValue<br>visible</p>                                                                                |
| Checkbox                                | <p>moreInfoButtonClicked<br>value<br>displayValue<br>visible</p>                                                       |
| Radio                                   | <p>value<br>displayValue<br>visible</p>                                                                                |
| Grupa radio                             | <p>value<br>displayValue<br>visible</p>                                                                                |
| Grupa kafli                             | <p>content - zwróci displayValue<br>value<br>displayValue<br>visible</p>                                               |
| Kafel                                   | visible                                                                                                                |
| Oświadczenia                            | <p>statementsItemControl<br>value<br>displayValue<br>visible</p>                                                       |
| Slider                                  | <p>sliderValue<br>value - (defaultValue)<br>displayValue<br>visible</p>                                                |
| Step Slider                             | <p>sliderValue - value<br>value - (defaultValue)<br>displayValue<br>visible</p>                                        |
| Slider podwójnego zakresu               | <p>value<br>displayValue<br>visible</p>                                                                                |
| Sekcja                                  | folded                                                                                                                 |
| Sekcja checkbox                         | <p>value<br>displayValue<br>visible</p>                                                                                |
| Sekcja powtarzalna                      | folded                                                                                                                 |
| Pomoc kontekstowa                       | <p>value<br>displayValue<br>visible</p>                                                                                |
| Wybór produktu                          | <p>variantId<br>productId<br>value<br>displayValue<br>visible</p>                                                      |
| Picture card                            | <p>value<br>displayValue<br>visible</p>                                                                                |
| Załączniki                              | <p>totalFilesSize<br>fileNames<br>externalIds<br>value<br>displayValue<br>visible</p>                                  |
| Komponent potwierdzenia danych          | <p>wasEdited<br>value<br>displayValue<br>visible</p>                                                                   |
| Skaner kodów QR                         | <p>value<br>displayValue<br>visible</p>                                                                                |
| Mapa                                    | <p>value<br>displayValue<br>visible</p>                                                                                |
| Komponent specjalizowany                | <p>value<br>displayValue<br>visible</p>                                                                                |
| Frontend component                      | <p>value<br>displayValue<br>visible</p>                                                                                |

**Odwoływanie się do atrybutów w warunkach:** Jak wspomniano, do odczytu atrybutu służy `getData(id, "atrybut")`. Jednak w praktyce większość warunków sprawdza po prostu wartość pola (`value`) lub jego widoczność/aktywność. Dla wygody platforma Eximee udostępnia dedykowane metody API:

* **`getValue("ID")`** – zwraca `value` komponentu o wskazanym ID (najczęściej używane).
* **`isVisible("ID")`** – zwraca informację o widoczności komponentu (ciąg `"true"`/`"false"`).

*(Niektóre komponenty specjalne posiadają dodatkowe metody, np. do obsługi grup oświadczeń – opisane dalej.)*

> *Przykład:* Jeśli pole tekstowe *AdresEmail* ma identyfikator `GesTextField5`, wówczas:
>
> * `getValue("GesTextField5")` zwróci wpisany adres e-mail,
> * `isVisible("GesTextField5")` zwróci `"true"` jeśli pole jest widoczne lub `"false"` jeśli zostało ukryte.

**Atrybuty specjalne – komponent Oświadczenia:** Dla komponentów typu *Oświadczenia* (lista zgód/akceptacji) dostępne są funkcje pozwalające sprawdzić, czy konkretne oświadczenie zostało zaznaczone. Metoda **`getStatementValue("ID_KOMPONENTU", "MID_OŚWIADCZENIA")`** zwraca wartość danego oświadczenia (zgody) na tym komponencie. W nowszych wersjach funkcja ta może być dostępna pod nazwą `getStatementItem`. Użycie jest następujące: np. `getStatementValue("Zgody1", "newsletter") == "true"` zwróci `true`, jeśli w komponencie o ID *Zgody1,* oświadczenie o identyfikatorze (MID) *newsletter* jest zaakceptowane przez użytkownika.

## Zaawansowany edytor warunków

Eximee Designer udostępnia **zaawansowany edytor warunków**, który ułatwia tworzenie, edycję i weryfikację wyrażeń warunkowych. Edytor ten został wyposażony w następujące funkcje:

* **Kolorowanie składni:** składnia wyrażeń JavaScript jest podświetlana kolorami, co zwiększa czytelność złożonych warunków.
* **Automatyczne podpowiedzi:** podczas edycji warunku wyświetlane są podpowiedzi dostępnych zmiennych i pól formularza, a także podpowiedzi elementów API Eximee oraz często używanych metod JS.
* **Obsługa prefiksu "`js:"`:** nie ma potrzeby ręcznie wpisywać przed warunkiem prefiksu `"js:"` – edytor sam go pomija w widoku i automatycznie dodaje w kodzie źródłowym przy zapisie warunku. Dzięki temu użytkownik wpisuje tylko właściwe wyrażenie, a platforma dba o poprawny format.

**Gdzie używany jest edytor warunków:** Zaawansowany edytor jest wykorzystywany w polach na właściwości komponentu takie jak: **warunek widoczności**, **warunek aktywności (edycji)** oraz **warunek wymagalności**. Te trzy właściwości każdego komponentu formularza korzystają z opisywanego edytora i pozwalają na wpisanie formuły decydującej odpowiednio o tym, czy komponent jest widoczny, aktywny (odblokowany) oraz czy jest wymagany do wypełnienia.

<figure><img src="/files/pWSG1ZJk0zlbcsY1bBul" alt=""><figcaption></figcaption></figure>

**Podpowiedzi składni w edytorze:** W trybie edycji warunku można skorzystać z podpowiedzi, naciskając klawisze **Ctrl + Spacja**. Spowoduje to wyświetlenie listy dostępnych elementów do użycia. Wśród podpowiedzi znajdują się m.in.:

* *Standardowe funkcje i właściwości JavaScript:* `parseInt()`, `parseFloat()`, właściwość `.length` (długość tekstu) czy `size` (rozmiar listy), a także inne często używane konstrukcje (np. słowo kluczowe `empty` do sprawdzania pustych wartości).
* *API Eximee:* funkcje dostarczane przez platformę, takie jak `getValue()`, `getData()`, `isVisible()` czy `getStatementValue()`, pojawią się na liście podpowiedzi, przypominając o ich dostępności.
* *Identyfikatory pól i zmiennych:* edytor automatycznie podpowiada **MIDy komponentów** dostępnych w danym formularzu (wraz z ich technicznym ID w nawiasie) oraz nazwy zmiennych sesyjnych używanych we wniosku. Dzięki temu można szybko wstawić referencję do konkretnego pola bez konieczności pamiętania jego dokładnego identyfikatora.

<figure><img src="/files/RMIoMcaC7ypsVNl0h8Ex" alt=""><figcaption></figcaption></figure>

> **Tip:** W przypadku dużej liczby pól, aby szybko znaleźć na liście podpowiedź dla konkretnego komponentu, zacznij pisać jego nazwę (MID) – lista zostanie przefiltrowana. Podpowiedzi pomagają unikać literówek w ID oraz umożliwiają poznanie dostępnych funkcji.

## Przykłady użycia wyrażeń warunkowych

Poniżej znajduje się kilka przykładowych wyrażeń warunkowych wraz z opisem ich działania. Każdy przykład pokazuje fragment kodu użytego w definicji warunku oraz wyjaśnienie:

* ```js
  parseInt(getValue("GesTextField3")) > 5
  ```

  – porównanie całkowitoliczbowe: sprawdza, czy wartość liczbowa wpisana w polu tekstowym `GesTextField3` jest większa od 5.
* ```js
  parseFloat(getValue("GesTextField5")) < 200.001
  ```

  – porównanie zmiennoprzecinkowe: sprawdza, czy wartość z pola tekstowego `GesTextField5` (np. kwota lub liczba z miejscami po przecinku) jest mniejsza od 200.001.
* ```js
  getValue("GesCheckbox1") == "true"
  ```

  – porównanie logiczne (równość): sprawdza, czy pole typu *Checkbox* o ID `GesCheckbox1` jest zaznaczone (ma wartość `"true"`).
* ```js
  getValue("GesCheckbox1") != "true"
  ```

  – porównanie logiczne (różność): sprawdza, czy ten sam checkbox **nie** jest zaznaczony (czyli wartość różna od `"true"` – w praktyce `"false"` lub brak wartości).
* ```js
  getValue("GesRadioGroup1") == "audi"
  ```

  – porównanie tekstowe: sprawdza, czy w grupie przycisków Radio o ID `GesRadioGroup1` wybrano opcję o wartości `"audi"` (np. jedna z marek samochodów).
* ```js
  !!getValue("nazwiskoZew")
  ```

  – podwójna negacja: sprawdza, czy dana wartość nie jest pusta. Dwa wykrzykniki konwertują wartość na typ boolean – wyrażenie zwróci `true`, jeśli zmienna lub pole `nazwiskoZew` posiada niepustą wartość (np. użytkownik wpisał nazwisko), a `false` w przeciwnym razie.
* ```js
  !getValue("nazwiskoZew")
  ```

  – negacja: sprawdza, czy wartość jest pusta. Zwróci `true`, jeśli pole/zmienna `nazwiskoZew` **nie ma wartości** (np. użytkownik nic nie wpisał), co w JavaScript jest równoznaczne z wartością *falsy* (np. pusty string `""`).
* ```js
  getStatementItem("GesStatementPopup1", "oswiadczenie1") == "true"
  ```

  – warunek dla komponentu typu *Oświadczenia*: sprawdza, czy w komponencie o ID `GesStatementPopup1` zaznaczono oświadczenie o identyfikatorze (MID) `oswiadczenie1` (czyli czy użytkownik zaakceptował to oświadczenie).
* ```js
  getStatementItem("@GesStatementFlat5", "zdrowotne") == "false"
  ```

  – podobny warunek dla *Oświadczenia* wewnątrz komponentu złożonego: sprawdza, czy oświadczenie `zdrowotne` w komponencie o ID `GesStatementFlat5` (osadzonym w komponencie złożonym, stąd prefiks `@`) **nie zostało** zaznaczone przez użytkownika.
* ```js
  !!!(getValue("@GesTextField13") || getValue("@GesTextField8"))
  ```

  – przykład warunku wymagalności: potrójna negacja przed wyrażeniem w nawiasie sprawdza, czy *oba* pola tekstowe `GesTextField13` oraz `GesTextField8` są puste. Wewnątrz nawiasu operator `||` zwróci pierwszą niepustą wartość (lub pustą, jeśli obie wartości są puste). Zastosowanie `!` odwraca wynik, a `!!` konwertuje go do booleana. Efektem całości jest `true` tylko wtedy, gdy **oba pola są puste** (wtedy np. inne pole staje się wymagane). Gdy którekolwiek pole ma wartość, wyrażenie zwróci `false` (czyli warunek wymagalności nie jest spełniony, więc np. dane pole nie musi być wymagane).
* ```js
  getValue("@GesCombobox1") != 2 && getValue("@GesCombobox1") > 0
  ```

  – złożony warunek dla listy wyboru (Combobox): sprawdza dwie rzeczy jednocześnie – czy wartość wybrana w polu Combobox `GesCombobox1` **nie jest równa 2** oraz czy jest **większa od 0**. Taki warunek mógłby służyć np. do weryfikacji wyboru innego niż domyślny (zakładając, że wartość `0` oznacza brak wyboru, a `2` to jakaś opcja wykluczona).
* ```js
  isVisible("@GesTextField1") == "true"
  ```

  – sprawdzenie stanu widoczności: warunek zwróci `true`, jeśli komponent o ID `GesTextField1` jest aktualnie widoczny (np. inny warunek go nie ukrył). Można to wykorzystać, aby uzależnić działanie od tego, czy inne pole jest na ekranie.
* ```js
  getValue("GesTextField5").length == 10
  ```

  – sprawdzenie długości tekstu: warunek zwraca `true`, jeśli w polu tekstowym `GesTextField5` wpisano dokładnie 10 znaków. Może to służyć np. do walidacji formatu (sprawdzenie czy numer ma wymaganą długość).

*(W powyższych przykładach użyto przykładowych identyfikatorów wygenerowanych przez system, takich jak **GesTextField5**. W rzeczywistym projekcie zaleca się nadawanie polom czytelnych identyfikatorów biznesowych (MID), co ułatwia późniejsze odwoływanie się do nich w warunkach)*

### Wyrażenia warunkowe w komponentach złożonych i biznesowych

* Wewnątrz komponentu złożonego/biznesowego, aby jednoznacznie wskazać zmienną/pole z tego komponentu, poprzedź nazwę znakiem `@`:
  * `getValue("@nazwaZmiennej")`
  * Przykład: `getValue("@walutaDomyślna") == "USD"`.
  * Dlaczego? w trakcie ewaluacji warunku `@` rozwija się do identyfikatora komponentu, np. `getValue("@nazwaZmiennej")` → `getValue("GesComplexComponent1.nazwaZmiennej")`, co eliminuje kolizje nazw z formularzem głównym, na którym umieszczono komponent.
* Gdy istnieje kolizja nazw (ta sama zmienna/pole w głównym wniosku i w komponencie) lub chcesz być precyzyjny — użyj `@` nawet jeśli warunek działa bez niego.
* Dobra praktyka: w komponentach złożonych/biznesowych zawsze poprzedzaj nazwy zmiennych/pól znakiem `@` w wyrażeniach warunkowych, chyba że umyślnie chcesz się odwołać do zmiennej/pola z formularza głównego - wtedy pomiń `@`
* Uwaga: zmienne predefiniowane przez system umieszczane są na głównym formularzu, odwołujemy się zatem do nich bezpośrednio po nazwie pomijając znak `@`.

Przykłady:

* Główny formularz: `getValue("walutaDomyślna") == "USD"`.
* Wewnątrz komponentu (precyzyjnie do zmiennej z tego komponentu): `getValue("@walutaDomyślna") == "USD"`.

## FAQ – Najczęstsze pytania

**Jak ustawić, żeby komponent wyświetlał się warunkowo (np. po zaznaczeniu checkboxa)?**\
Należy skorzystać z właściwości **Warunek widoczności (visibleCondition)** dostępnej w panelu właściwości komponentu. W pole warunku wpisujemy wyrażenie, które ma zwracać `true` gdy komponent ma być widoczny. Przykładowo: jeżeli pole *SekcjaDodatkowa* ma pokazywać się po zaznaczeniu checkboxa *PokazSekcje (id=GesCheckbox7)*, to ustawiamy warunek widoczności: `getValue("GesCheckbox7") == "true"`. Gdy użytkownik zaznaczy dany checkbox, warunek zostanie spełniony i *SekcjaDodatkowa* stanie się widoczna.

**Warunek nie odświeża się po zmianie innego pola – co robię źle?**\
Prawdopodobnie brakuje ustawienia **nasłuchiwania**. Aby komponent reagował na zmiany wartości innego pola używanego w wyrażeniu, trzeba ustawić dla niego atrybut **ListeningOn** (Nasłuchiwanie) wskazujący na to pole. Innymi słowy, komponent z warunkiem musi "nasłuchiwać" komponentu, od którego zależy warunek. W Eximee Designer zrobisz to w sekcji **Interakcje** właściwości komponentu – dodaj na liście Nasłuchiwanie identyfikator zależnego pola. Po poprawnym ustawieniu nasłuchiwania, zmiana wartości jednego pola automatycznie spowoduje ponowną ewaluację warunku w drugim polu.

**Jak sprawdzić w warunku, czy pole jest puste lub wypełnione?**\
Można to zrobić na kilka sposobów. Najprostszym jest wykorzystanie faktu, że pusty string w JavaScript jest wartością *falsy* (nieprawdziwą). Przykładowo: wyrażenie `!getValue("PoleX")` zwróci `true`, gdy *PoleX* jest puste (negacja pustego stringa da true). Odwrotnie, wyrażenie `!!getValue("PoleX")` zwróci `true`, tylko jeśli *PoleX* ma jakąś wartość (podwójna negacja konwertuje wartość na typ boolean zachowując jej "prawdę"). Alternatywnie można porównać bezpośrednio do pustego ciągu: `getValue("PoleX") == ""` (puste) lub `getValue("PoleX") != ""` (wypełnione).

**Czy w wyrażeniu warunkowym muszę dodawać przedrostek `js:`?**\
Nie. W edytorze Eximee Designer wpisujemy tylko samo wyrażenie warunkowe, bez żadnych prefixów. Prefiks `"js:"` jest dodawany automatycznie w kodzie źródłowym i służy wewnętrznie do oznaczenia, że warunek należy interpretować jako skrypt JavaScript. Jeśli podejrzysz konfigurację XML wniosku, zobaczysz tam `condition="js:...twoje_wyrażenie..."`, ale w interfejsie Designer nie trzeba (ani nie powinno się) tego pisać samodzielnie.

**Jak zdefiniować warunek, który jest zawsze spełniony (zawsze prawdziwy)?**\
Jeśli chcemy, by dana akcja/warunek był *zawsze* prawdziwy (np. aby element był zawsze widoczny lub jakaś akcja zawsze się wykonywała), możemy jako wyrażenie wpisać stałą prawdziwą. W praktyce wystarczy wpisać wartość **`true`**. Edytor doda odpowiedni prefix i warunek będzie traktowany jako zawsze spełniony. Alternatywnie, można wpisać **`js:true`** w surowej konfiguracji – efekt będzie taki sam. Podobnie, warunek zawsze fałszywy można uzyskać wpisując `false` (co spowoduje np. że dany komponent nigdy nie będzie widoczny sam z siebie).

**Czy mogę używać dowolnych funkcji JavaScript w warunkach?**\
Obsługiwane są podstawowe funkcje i operatory JavaScript, zwłaszcza te podpowiadane przez edytor (jak `parseInt`, `parseFloat`, operatory logiczne itp.). Należy jednak pamiętać, że warunek jest wykonywany w kontekście przeglądarki użytkownika, więc nie powinien zawierać wywołań, które mogą być niezrozumiałe lub niedostępne. Dobrą praktyką jest ograniczenie się do prostych operacji i korzystanie z API udostępnianego przez platformę Eximee (np. `getValue`, `getData`, itp.) dla spójności i wydajności. Bezpośrednie odwoływanie się do elementów DOM czy zmiennych globalnych nie jest wspierane i może powodować błędy. Jeśli potrzebujesz skomplikowanej logiki, rozważ umieszczenie jej w kodzie walidatora lub usługi.

[^1]: Ja bym chyba nie naprowadzal czytających na inne metody tym bardziej że moga one powodować problemy z wydajnością.

[^2]: przydałby sie tu link


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.eximee.com/budowanie-aplikacji/interfejs-uzytkownika/formularze/dynamicznosc-formularza/jezyk-wyrazen.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
