# Model danych na interfejsie

### Wiązanie pól formularza z modelem danych

Kiedy model danych jest już zdefiniowany i podpięty, możemy w **formularzu wniosku** powiązać konkretne pola (komponenty UI) z polami modelu. W edytorze formularza każdy komponent, który przechowuje jakąś wartość (np. pole tekstowe, pole wyboru, data itp.), posiada właściwość **"Klucz modelu danych"**. Wystarczy wpisać w to pole klucz zdefiniowany w naszym modelu, aby dane z tego komponentu zostały związane z odpowiednim miejscem w modelu. Od tego momentu komponent staje się **dwukierunkowo związany** (two-way binding) z modelem danych – podczas inicjalizacji formularza wartość z modelu (jeśli istnieje) zostanie wczytana do pola, a gdy użytkownik wypełni lub zmieni tę wartość, zostanie ona zapisana z powrotem do modelu danych przy zapisie wniosku. Oznacza to, że **po zapisaniu formularza, wszystkie powiązane pola aktualizują odpowiadające im wartości w modelu danych**, dzięki czemu model zawsze odzwierciedla bieżący stan danych wniosku.

<figure><img src="/files/gNjExodM2nfgLyMPgq1d" alt=""><figcaption><p>Ilustracja 1. Przykład dwukierunkowego związania za pomocą klucza modelu danych</p></figcaption></figure>

{% hint style="info" %}
**Info:** Można też stosować **jednokierunkowe powiązanie** pola z modelem w sytuacji, gdy chcemy jedynie wyświetlić wartość z modelu na formularzu, ale nie aktualizować jej na podstawie wejścia użytkownika. Taki jednorazowy odczyt realizuje się np. poprzez wstawienie odwołania do zmiennej modelu w tekstach (etykietach) albo użycie właściwości komponentu **`valueSourceId`**, która pobierze wartość z modelu tylko do odczytu. Standardowo jednak, dla pól edytowalnych korzystamy z powiązania dwustronnego, aby wprowadzone dane zostały zapisane.
{% endhint %}

<figure><img src="/files/OkffjOMUn0yh60ncJRLX" alt=""><figcaption><p>Ilustracja 2. Przykład jednokierunkowego związania za pomocą valueSourceId</p></figcaption></figure>

Należy pamiętać, że **nie każdy komponent formularza można powiązać z modelem**. Model danych ma sens tylko dla pól, które przechowują wartości. W związku z tym nie powiążemy z modelem np. takich elementów jak:

* linki (odnośniki),
* pola typu CAPTCHA,
* pojedyncze przyciski radio (poza grupami radiobuttonów),
* okna popup,
* kody QR (jeśli występują jako obraz/element dekoracyjny).

Wszystkie pozostałe pola (tekstowe, liczbowe, wybory z listy, checkboxy, daty, sekcje itp.) mogą i **powinny** być powiązane z modeliem danych, jeśli ich wartość ma być zachowana lub użyta poza samym formularzem. Powiązanie to zapewnia spójność – każda dana wprowadzona przez użytkownika ma swoje miejsce w modelu, skąd może być dalej przetwarzana (np. przekazana do procesu).

Wartości z modelu danych mogą być wykorzystywane w artefakcie Treść (TextContent) np.

{% code expandable="true" %}

```java
<p>
    Przykładowa treść ${model:client.name}
</p>

```

{% endcode %}

### Obsługa pól tablicowych (list)

Model danych umożliwia definiowanie pól będących kolekcjami (tablicami) obiektów lub wartości prostych. Jeśli w modelu dane pole ma mieć wiele powtórzeń (np. lista adresów, listę produktów, itp.), należy ustawić jego `multiplicityMax` > 1 (np. `null` dla braku górnego limitu) oraz przygotować odpowiednie źródło danych zwracające kolekcję. W formularzu takie pole może być reprezentowane np. przez **Sekcję powtarzalną** (Repeatable Section) z odpowiednimi polami wewnątrz. Ważne jest, by **poprawnie odwoływać się do elementów tablicy** w kluczach modelu:

* `kolekcja[].pole` – odwołanie do *wszystkich* wystąpień pola w kolekcji (zwraca całą listę wartości lub np. konkatenację, zależnie od kontekstu),
* `kolekcja[0].pole` – odwołanie do pola w **pierwszym** elemencie kolekcji (indeks 0 oznacza pierwszy element, 1 - drugi, itd.),
* **Uwaga:** Nie można pomijać indeksu! Składnia `kolekcja.pole` (bez `[]` lub indeksu) jest niepoprawna i spowoduje błąd uniemożliwiający uruchomienie formularza. Zawsze należy użyć notacji tablicowej przy odwołaniu do pól elementów kolekcji.
* Dla sekcji powtarzalnych w formularzu, w których użytkownik może dynamicznie dodawać/usuwać elementy, Eximee używa zmiennej `_rowIdx` przypisanej do danej sekcji, aby przekazywać indeks bieżącego wiersza. W kluczu modelu pojawia się wtedy identyfikator w postaci `NazwaSekcji_rowIdx`. Na przykład, jeżeli sekcja powtarzalna jest powiązana z kolekcją `produkty[]` i ma pole `nazwa`, to klucz pola w sekcji może wyglądać: `produkty[NazwaSekcji_rowIdx].nazwa`. Mechanizm ten zapewnia powiązanie każdego dynamicznie dodanego pola z unikalnym indeksem w modelu.

<figure><img src="/files/Vettv44POa2aOva4TvFO" alt=""><figcaption><p>Ilustracja 3. Podpięcie pola tablicowego do sekcji powtarzalnej</p></figcaption></figure>

<figure><img src="/files/sFOEVJLkL96sYEMUXm6H" alt=""><figcaption><p>Ilustracja 4. Podpięcie Comboboxa znajdującego się w sekcji powtarzalnej do modelu danych</p></figcaption></figure>

### dataModelTransformer

Dzięki **dataModelTransformer**, znajdującym się w xml (zakładka "Źródło") można wpłynąć na dane, które po zapisie wniosku spadną do modelu danych.

Aby wykorzystać tę funkcjonalność, należy w xml (w ecMetadata wewnątrz iftTemplateMetadata) dodać skrypt, który będzie mógł zmodyfikować zapisywany model.

Przykład mapowania zmiennych sesyjnych do modelu danych:

{% code expandable="true" %}

```java
<dataModelTransformer>
  <content>
      function transform(input) {
          input.put('bazaOfert.KredytNr', api.form.v1.value("agreementId"));
          input.put('bazaOfert.CIF', api.form.v1.value("cif"));
          if(api.form.v1.value("GesCheckbox5") == "false"){
              input.put('daneKlientaCis.NumerTelefonu', api.form.v1.value("phoneNumber"));
              input.put('daneKlientaCis.AdresEmail', api.form.v1.value("email"));
          }  
          return input;
      }
  </content>
</dataModelTransformer>
```

{% endcode %}

Przykład mapowania wartości z niewidocznych pól do modelu danych:

{% code expandable="true" %}

```java
<dataModelTransformer>
  <content>
      function transform(input) {
              for (let node of api.form.v1.invisibleFormNodes()) {
                  if(node.model()) {
                      input.put(node.model(), '');
                  }
              }
              return input;
          }
  </content>
</dataModelTransformer>
```

{% endcode %}


---

# 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/praca-z-komponentami-bazowymi/model-danych-na-interfejsie.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.
