<!-- https://abap2ui5.github.io/docs/cookbook/model/binding -->

# Binding

In abap2UI5 you share data between your ABAP code and the UI5 frontend with `client->_bind( )`. There is only one binding, and it works **in both directions**: when the value is changed in an editable control, the framework writes it back to your ABAP attribute before the next event handler runs. Only the paths the user actually edited are transported back (a delta), so read-only data costs nothing on the way back.

## Displaying Data
Bind an attribute to a display-only control (e.g. `text`) — nothing is editable there, so nothing syncs back:

```abap
CLASS zcl_app_hello_world DEFINITION PUBLIC.

  PUBLIC SECTION.
    INTERFACES z2ui5_if_app.
    DATA name TYPE string.

  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_app_hello_world IMPLEMENTATION.
  METHOD z2ui5_if_app~main.

    DATA(view) = z2ui5_cl_ui5_view_builder=>factory(
        )->ele( n = `View` ns = `mvc`
            )->a( n = `xmlns`     v = `sap.m`
            )->a( n = `xmlns:mvc` v = `sap.ui.core.mvc`

            )->ele( `Page`
                )->a( n = `title` v = `abap2UI5 - Hello World`

                )->tag( `Text`
                    )->a( n = `text` v = `My Text`
                )->tag( `Text`
                    )->a( n = `text` v = client->_bind( name ) ).

    client->view_display( view->stringify( ) ).

  ENDMETHOD.
ENDCLASS.
```
This method works with tables, trees, and other nested data structures — see [Tables](/cookbook/model/tables) and [Trees](/cookbook/model/trees).

## Editing Data
Bind an attribute to an editable control (e.g. `input`). After an event, the framework has already synced the user's changes back to your ABAP attribute:

```abap
CLASS zcl_app_hello_world DEFINITION PUBLIC.

  PUBLIC SECTION.
    INTERFACES z2ui5_if_app.
    DATA name TYPE string.

  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_app_hello_world IMPLEMENTATION.
  METHOD z2ui5_if_app~main.

    DATA(view) = z2ui5_cl_ui5_view_builder=>factory(
        )->ele( n = `View` ns = `mvc`
            )->a( n = `xmlns`     v = `sap.m`
            )->a( n = `xmlns:mvc` v = `sap.ui.core.mvc`

            )->ele( `Page`
                )->a( n = `title` v = `abap2UI5 - Hello World`

                )->tag( `Text`
                    )->a( n = `text` v = `Enter your name`
                )->tag( `Input`
                    )->a( n = `value` v = client->_bind( name )
                )->tag( `Button`
                    )->a( n = `text`  v = `post`
                    )->a( n = `press` v = client->_event( `POST` ) ).

    client->view_display( view->stringify( ) ).


    CASE client->get( )-event.
      WHEN `POST`.
        client->message_box_display( |Your name is { name }.| ).
        RETURN.
    ENDCASE.

  ENDMETHOD.
ENDCLASS.
```


::: warning **Bound Attributes Must Be Public**
`_bind( )` resolves your class attributes from outside the controller via dynamic ASSIGN, and it only sees the `PUBLIC SECTION`. Passing a `PROTECTED` or `PRIVATE` attribute — or a local variable — is **not** silent: the framework finds no attribute for the reference and raises

```
BINDING_ERROR - No class attribute for binding found -
Please check if the bound values are public attributes of your class
```

which reaches the browser as a 500 and is shown in the error view. The
compiler cannot catch it (the call takes `TYPE data`), but the runtime says
exactly what is wrong.

Always declare bound data in `PUBLIC SECTION`. This resembles the PAI/PBO logic, where data lived in global variables. See also [Life Cycle → Lifecycle Pitfalls](/cookbook/event_navigation/life_cycle#lifecycle-pitfalls).
:::

## Binding to Structures

When the bound attribute is a structure, refer to a field directly with the `-` component selector. The framework generates one model path per field — the structure name and the component name, in upper case, joined by `/`:

```abap
TYPES: BEGIN OF ts_order,
         customer TYPE string,
         material TYPE string,
         quantity TYPE i,
       END OF ts_order.

DATA edit_row TYPE ts_order.

...

)->tag( `Input`
    )->a( n = `value` v = client->_bind( edit_row-customer )   " resolves to {/EDIT_ROW/CUSTOMER}
)->tag( `Input`
    )->a( n = `value` v = client->_bind( edit_row-material )
)->tag( `Input`
    )->a( n = `value` v = client->_bind( edit_row-quantity )
```

Nested structures follow the same rule recursively (`edit_row-address-city` → `/EDIT_ROW/ADDRESS/CITY`). Internal tables of structures use one row context per item — see [Tables](/cookbook/model/tables).

## Data-Type Mapping

ABAP and UI5 do not share a type system. When ABAP values cross to the frontend they are serialized to JSON and then read by UI5 controls. The table below is the reference for how each ABAP type travels on the wire and which UI5 binding it pairs with. For the controls that need an explicit `type:` or formatter, the linked sections in [Formatter](/cookbook/model/formatter) show the full binding-string pattern.

| ABAP type            | On the wire        | Typical UI5 use                                        | Notes                                                                |
| -------------------- | ------------------ | ------------------------------------------------------ | -------------------------------------------------------------------- |
| `string`, `c LENGTH n` | JSON string        | `Input`, `Text`                                        | Works without a formatter.                                           |
| `i`, `int8`, `b`, `s` | JSON number       | `Input type="Number"`, `Text`                          | Returned as string from inputs; cast back if you need an integer.    |
| `p LENGTH n DECIMALS m`, `decfloat16`, `decfloat34` | JSON number | `Input`, `Text` + `sap.ui.model.type.Float`/`Currency` | The decimals travel as written (`1234.56`), no rounding through a binary float. Locale formatting needs an explicit type — see [Currency](/cookbook/model/formatter#currency). |
| `f` (binary float)   | JSON number        | `Input`, `Text` + `sap.ui.model.type.Float`            | Binary float — prefer `p` or `decfloat34` for monetary values to avoid rounding drift. |
| `n LENGTH n`         | JSON string of digits | `Input` + `sap.ui.model.odata.type.String` with `isDigitSequence: true` | Without the constraint, leading zeros render literally — see [Digit Sequence](/cookbook/model/formatter#digit-sequence). |
| `d`                  | 8-char string `YYYYMMDD` | `DatePicker` + `sap.ui.model.type.Date`             | Not an ISO date — a formatter is required for explicit locale or pattern control. See [Date](/cookbook/model/formatter#date). |
| `t`                  | 6-char string `HHMMSS` | `TimePicker` + `sap.ui.model.type.Time`                | Same pattern as `d` — see [Time](/cookbook/model/formatter#time).    |
| `abap_bool` (`X`/` `) | JSON `true` / `false` | `CheckBox`, `Switch` — bind it directly | The framework maps the BOOLEAN ABAP TYPES to a JSON boolean and back, so no expression and no formatter is needed. A flag typed `c LENGTH 1` instead is just a string — see [Boolean](/cookbook/model/formatter#boolean). |
| `timestamp`, `timestampl` | JSON number (the packed digits) | `DateTimePicker` + ABAP-side conversion or a formatter | No built-in UI5 type reads them directly. Split into `d` + `t` or convert to a `yyyyMMddHHmmss` string — see [Timestamp](/cookbook/model/formatter#timestamp). |
| `utclong` | JSON string, ISO-like (`2026-08-21T14:00:00Z`) | `DateTimePicker` + `Formatter.DateCreateObject` | The one timestamp type that arrives in a shape `new Date( )` parses — see [The formatters abap2UI5 ships](/cookbook/model/formatter#the-formatters-abap2ui5-ships). |
| `xstring`            | binary — must be base64-encoded in ABAP before binding | `Image`, `FileUploader`, `pdf_viewer`                  | The framework does not auto-encode. Convert with `cl_web_http_utility=>encode_x_base64( )` (or `cl_http_utility=>if_http_utility~encode_x_base64( )` on older releases) — see [PDF](/cookbook/device_capabilities/pdf) and [Upload / Download](/cookbook/device_capabilities/upload_download). |
| structure            | JSON object         | Bind individual fields with `struct-field`             | One model path per field — see [Binding to Structures](#binding-to-structures). |
| internal table       | JSON array          | `Table`, `List`, `Tree`                                | One row context per item — see [Tables](/cookbook/model/tables) and [Trees](/cookbook/model/trees). |

When a value looks wrong, the fix is almost always a UI5-side `type` (e.g. `sap.ui.model.type.Date`, `sap.ui.model.type.Float`) or an abap2UI5 [Formatter](/cookbook/model/formatter). The shape is always the same — build a JSON binding string with `parts` and `type`, using `path = abap_true` on `_bind` to inject the raw model path:

```abap
)->tag( `Input`
    )->a( n = `value` v = |\{ parts: [ `{ client->_bind( val = amount   path = abap_true ) }`,
                                       `{ client->_bind( val = currency path = abap_true ) }` ],
                              type: 'sap.ui.model.type.Currency' \}|
```

See [Formatter](/cookbook/model/formatter) for the full example with `formatOptions`, `constraints`, and read-only display variants.

<!-- samples:start (generated by scripts/link-samples.mjs — do not edit) -->

## Working Samples

Complete apps from the [sample catalog](https://github.com/abap2UI5/samples/blob/main/SAMPLES.md)
that use what this page describes. Each is a single class — pull the repository with
[abapGit](https://abapgit.org) and start it with `?app_start=<class>`.

| Sample | Class |
|---|---|
| Basics II — Data Binding: Input and Button | [`Z2UI5_CL_SMP_APP_494`](https://github.com/abap2UI5/samples/blob/main/src/01/z2ui5_cl_smp_app_494.clas.abap) |
| Types for Integer, Decimal, Date and Time | [`Z2UI5_CL_SMP_APP_047`](https://github.com/abap2UI5/samples/blob/main/src/01/z2ui5_cl_smp_app_047.clas.abap) |
| Structure Fields and INCLUDEs | [`Z2UI5_CL_SMP_APP_166`](https://github.com/abap2UI5/samples/blob/main/src/01/z2ui5_cl_smp_app_166.clas.abap) |
| Single Table Cell (tab_index) | [`Z2UI5_CL_SMP_APP_144`](https://github.com/abap2UI5/samples/blob/main/src/01/z2ui5_cl_smp_app_144.clas.abap) |
| Dynamic Table Typed at Runtime (RTTI) | [`Z2UI5_CL_SMP_APP_061`](https://github.com/abap2UI5/samples/blob/main/src/01/z2ui5_cl_smp_app_061.clas.abap) |

<!-- samples:end -->
