Skip to content

Commit 7e7f9b7

Browse files
committed
Replace follow_up_action with action method across cookbook
Update all cookbook code samples and prose so that backend-triggered frontend events use the new client->action( val = ..., t_arg = ... ) method instead of the deprecated client->follow_up_action( client->_event_client( ... ) ) pattern. follow_up_action is no longer the recommended call. Rewrite the four browser interaction pages whose custom controls (_z2ui5( )->focus/scrolling/timer and the document.title JS pattern) are now redundant — they can be driven directly from the backend via the corresponding cs_event constants: title.md -> cs_event-set_title focus.md -> cs_event-set_focus scrolling.md -> cs_event-scroll_to / cs_event-scroll_into_view timer.md -> cs_event-start_timer (re-arm in the handler to repeat) Also update soft_keyboard.md to use cs_event-keyboard_set_mode, and barcode_scanning.md to use cs_event-set_focus and cs_event-play_audio, removing the previous raw-JavaScript follow-up patterns. Extend frontend.md with the new cs_event constants (set_title, set_focus, scroll_to, scroll_into_view, start_timer, keyboard_set_mode, clipboard_copy, clipboard_app_state, history_back) and explain the relationship between _event_client (inline frontend) and the new action method (frontend event triggered from the backend).
1 parent 3b21193 commit 7e7f9b7

15 files changed

Lines changed: 170 additions & 233 deletions

File tree

docs/cookbook/browser_interaction/clipboard.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ CLASS z2ui5_cl_sample_clipboard IMPLEMENTATION.
3131
)->stringify( ) ).
3232
3333
WHEN client->check_on_event( `COPY` ).
34-
client->follow_up_action( client->_event_client(
34+
client->action(
3535
val = client->cs_event-clipboard_copy
36-
t_arg = VALUE #( ( mv_text ) ) ) ).
36+
t_arg = VALUE #( ( mv_text ) ) ).
3737
client->message_toast_display( `copied` ).
3838
3939
ENDCASE.

docs/cookbook/browser_interaction/focus.md

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,28 @@ outline: [2, 4]
33
---
44
# Focus
55

6-
abap2UI5 offers the custom control `_z2ui5( )->focus( )` to set the input focus from the backend. Pass a bound variable holding the target control's `id` — the framework moves the cursor to that field after the next `view_model_update( )`.
6+
Set the input focus from the backend with the `set_focus` frontend event. Pass the target control's `id` as the first argument — the framework moves the cursor to that field after the next roundtrip.
77

88
This is useful for guided data entry, barcode scanning, or any flow where the next field to focus depends on backend logic.
99

1010
#### Basic Usage
1111

12-
Bind a `focus_id` variable to the focus control. Update its value in any event handler and call `view_model_update( )` the browser focuses the matching input automatically:
12+
After processing an event, call `client->action( )` with `cs_event-set_focus` and the id of the input to focus next:
1313

1414
```abap
1515
CLASS z2ui5_cl_sample_focus DEFINITION PUBLIC.
1616
1717
PUBLIC SECTION.
1818
INTERFACES z2ui5_if_app.
19-
DATA one TYPE string.
20-
DATA two TYPE string.
21-
DATA focus_id TYPE string.
19+
DATA one TYPE string.
20+
DATA two TYPE string.
2221
2322
ENDCLASS.
2423
2524
CLASS z2ui5_cl_sample_focus IMPLEMENTATION.
2625
METHOD z2ui5_if_app~main.
2726
2827
IF client->check_on_init( ).
29-
focus_id = `id1`.
3028
3129
DATA(page) = z2ui5_cl_xml_view=>factory( )->page( ).
3230
page->simple_form(
@@ -35,33 +33,41 @@ CLASS z2ui5_cl_sample_focus IMPLEMENTATION.
3533
)->input(
3634
id = `id1`
3735
value = client->_bind_edit( one )
38-
submit = client->_event( |one_enter| )
36+
submit = client->_event( `ONE_ENTER` )
3937
)->label( `Two`
4038
)->input(
4139
id = `id2`
4240
value = client->_bind_edit( two )
43-
submit = client->_event( |two_enter| ) ).
41+
submit = client->_event( `TWO_ENTER` ) ).
4442
45-
page->_z2ui5( )->focus( client->_bind( focus_id ) ).
4643
client->view_display( page->stringify( ) ).
47-
44+
RETURN.
4845
ENDIF.
4946
5047
CASE client->get( )-event.
51-
WHEN `one_enter`.
52-
focus_id = `id2`.
53-
client->view_model_update( ).
54-
WHEN `two_enter`.
55-
focus_id = `id1`.
56-
client->view_model_update( ).
48+
WHEN `ONE_ENTER`.
49+
client->action( val = client->cs_event-set_focus
50+
t_arg = VALUE #( ( `id2` ) ) ).
51+
WHEN `TWO_ENTER`.
52+
client->action( val = client->cs_event-set_focus
53+
t_arg = VALUE #( ( `id1` ) ) ).
5754
ENDCASE.
5855
5956
ENDMETHOD.
6057
ENDCLASS.
6158
```
6259

63-
After the user presses Enter in `id1`, the backend sets `focus_id = id2` and the frontend moves the cursor to the second input. The same pattern works for any chain of fields.
60+
After the user presses Enter in `id1`, the backend fires `set_focus` for `id2` and the cursor moves to the second input. The same pattern works for any chain of fields.
61+
62+
#### Selection Range
63+
64+
To position the caret inside the field or pre-select a range, pass the start and end offsets as additional arguments:
65+
66+
```abap
67+
client->action( val = client->cs_event-set_focus
68+
t_arg = VALUE #( ( `id1` ) ( `0` ) ( `5` ) ) ).
69+
```
6470

6571
#### Barcode Scanning
6672

67-
Most barcode scanner devices emulate a keyboard. Combine the focus control with input fields to capture scans into the right field automatically — see [Barcode Scanning](../device_capabilities/barcode_scanning.md) for a full walkthrough.
73+
Most barcode scanner devices emulate a keyboard. Combine `set_focus` with input fields to capture scans into the right field automatically — see [Barcode Scanning](../device_capabilities/barcode_scanning.md) for a full walkthrough.

docs/cookbook/browser_interaction/scrolling.md

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,65 +3,71 @@ outline: [2, 4]
33
---
44
# Scrolling
55

6-
abap2UI5 offers the custom control `_z2ui5( )->scrolling( )` to read and set the scroll position of any container from the backend. Bind a name/value table of element IDs to scroll positions — the framework reports current positions back into that table on every roundtrip, and applies new positions to the DOM whenever the update flag is set.
6+
Scroll a control programmatically from the backend with two frontend events:
77

8-
This is useful for jump-to-top buttons, restoring scroll positions after navigation, or scrolling to a specific row after a backend search.
8+
- **`cs_event-scroll_to`** — scroll a container to a specific pixel position.
9+
- **`cs_event-scroll_into_view`** — bring a control into the viewport, wherever the surrounding scroll container currently sits.
910

10-
#### Basic Usage
11+
Useful for jump-to-top buttons, restoring positions after navigation, or revealing a row after a backend search.
1112

12-
Bind two variables to the control: a flag `setupdate` that triggers a write to the DOM, and an `items` table mapping element `id` to scroll position. Update the entry and call `view_model_update( )` — the browser scrolls the matching element:
13+
#### Scroll to a Position
14+
15+
Pass the control id and the vertical position. Optionally also a horizontal position and a scroll behavior (`auto`, `smooth`, or `instant`):
1316

1417
```abap
1518
CLASS z2ui5_cl_sample_scrolling DEFINITION PUBLIC.
1619
1720
PUBLIC SECTION.
1821
INTERFACES z2ui5_if_app.
19-
DATA mv_scrollupdate TYPE abap_bool.
20-
DATA mt_scroll TYPE z2ui5_if_types=>ty_t_name_value.
2122
2223
ENDCLASS.
2324
2425
CLASS z2ui5_cl_sample_scrolling IMPLEMENTATION.
2526
METHOD z2ui5_if_app~main.
2627
2728
IF client->check_on_init( ).
28-
INSERT VALUE #( n = `id_page` ) INTO TABLE mt_scroll.
29-
3029
DATA(page) = z2ui5_cl_xml_view=>factory( )->page( id = `id_page` ).
31-
page->_z2ui5( )->scrolling(
32-
setupdate = client->_bind_edit( mv_scrollupdate )
33-
items = client->_bind_edit( mt_scroll ) ).
34-
3530
page->footer( )->overflow_toolbar(
3631
)->button( text = `Top`
3732
press = client->_event( `SCROLL_TOP` )
3833
)->button( text = `Bottom`
3934
press = client->_event( `SCROLL_BOTTOM` ) ).
40-
4135
client->view_display( page->stringify( ) ).
4236
RETURN.
4337
ENDIF.
4438
4539
CASE client->get( )-event.
4640
WHEN `SCROLL_TOP`.
47-
mt_scroll[ n = `id_page` ]-v = `0`.
48-
mv_scrollupdate = abap_true.
49-
client->view_model_update( ).
50-
41+
client->action( val = client->cs_event-scroll_to
42+
t_arg = VALUE #( ( `id_page` ) ( `0` ) ) ).
5143
WHEN `SCROLL_BOTTOM`.
52-
mt_scroll[ n = `id_page` ]-v = `99999`.
53-
mv_scrollupdate = abap_true.
54-
client->view_model_update( ).
44+
client->action( val = client->cs_event-scroll_to
45+
t_arg = VALUE #( ( `id_page` ) ( `99999` ) ) ).
5546
ENDCASE.
5647
5748
ENDMETHOD.
5849
ENDCLASS.
5950
```
6051

61-
On every roundtrip the framework also writes the current scroll position of each tracked element back into `mt_scroll`, so the backend always knows where the user is. Setting `mv_scrollupdate = abap_true` switches the next update from read to write — the value in `mt_scroll` is applied to the DOM and the flag is reset by the frontend.
52+
The arguments for `scroll_to` are `id`, `scrollTop` (y, px), `scrollLeft` (x, px, optional), and `behavior` (optional):
53+
54+
```abap
55+
client->action( val = client->cs_event-scroll_to
56+
t_arg = VALUE #( ( `id_page` ) ( `500` ) ( `0` ) ( `smooth` ) ) ).
57+
```
6258

63-
#### Notes
59+
#### Scroll an Element into View
6460

65-
- Track multiple containers by inserting one row per element `id` into `mt_scroll`.
66-
- For relative scrolling (e.g. "500 pixels down"), read the current value from `mt_scroll`, adjust it in ABAP, and set `mv_scrollupdate = abap_true`.
67-
- See [sample 134](https://github.com/abap2UI5/samples/blob/main/src/z2ui5_cl_demo_app_134.clas.abap) for a full demo with top/up/down/bottom buttons.
61+
To reveal a specific control — e.g. a row after a search — use `scroll_into_view` with the target control's id:
62+
63+
```abap
64+
client->action( val = client->cs_event-scroll_into_view
65+
t_arg = VALUE #( ( `id_row_42` ) ) ).
66+
```
67+
68+
Additional optional arguments mirror the browser's `scrollIntoView` options: `behavior` (`smooth` | `auto` | `instant`), `block` (`start` | `center` | `end` | `nearest`), `inline` (`nearest` | `start` | `center` | `end`):
69+
70+
```abap
71+
client->action( val = client->cs_event-scroll_into_view
72+
t_arg = VALUE #( ( `id_row_42` ) ( `smooth` ) ( `center` ) ) ).
73+
```

docs/cookbook/browser_interaction/timer.md

Lines changed: 28 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,28 @@ outline: [2, 4]
33
---
44
# Timer
55

6-
abap2UI5 offers a custom control `z2ui5.Timer` that fires events after a set delay. This is handy for dashboards, status monitors, or any case that needs periodic data updates without user interaction.
6+
Fire a backend event after a delay with the `start_timer` frontend event. Handy for dashboards, status monitors, or any case that needs a delayed or periodic update without user interaction.
77

8-
Add the timer as a view element with `_z2ui5( )->timer( ... )`. These parameters apply:
8+
Pass the event name to fire and the delay in milliseconds:
99

10-
| Parameter | Description |
11-
|---------------|--------------------------------------------------|
12-
| `finished` | Event fired when the timer expires |
13-
| `delayms` | Delay in milliseconds before firing |
14-
| `checkactive` | Bind to an `abap_bool` to turn the timer on/off |
15-
| `checkrepeat` | If `abap_true`, the timer repeats automatically |
10+
```abap
11+
client->action(
12+
val = client->cs_event-start_timer
13+
t_arg = VALUE #( ( `REFRESH` ) ( `2000` ) ) ).
14+
```
1615

17-
#### Basic Usage
16+
After 2 seconds the browser triggers a backend roundtrip with the event name `REFRESH`, which you handle via `check_on_event` like any other event.
1817

19-
Embed the timer in your view and control it via data binding. The example below increments a counter every 2 seconds:
18+
#### Periodic Refresh
19+
20+
To get a repeating timer, simply re-arm it at the end of each handler:
2021

2122
```abap
2223
CLASS z2ui5_cl_sample_timer DEFINITION PUBLIC.
2324
2425
PUBLIC SECTION.
2526
INTERFACES z2ui5_if_app.
2627
DATA counter TYPE i.
27-
DATA check_timer_active TYPE abap_bool.
2828
2929
ENDCLASS.
3030
@@ -34,110 +34,45 @@ CLASS z2ui5_cl_sample_timer IMPLEMENTATION.
3434
CASE abap_true.
3535
3636
WHEN client->check_on_init( ).
37-
check_timer_active = abap_true.
38-
3937
client->view_display( z2ui5_cl_xml_view=>factory(
4038
)->page( `abap2UI5 - Timer`
4139
)->text( client->_bind( counter )
42-
)->_z2ui5( )->timer(
43-
checkactive = client->_bind( check_timer_active )
44-
delayms = `2000`
45-
finished = client->_event( `TIMER_FINISHED` )
46-
checkrepeat = abap_true
4740
)->stringify( ) ).
41+
client->action( val = client->cs_event-start_timer
42+
t_arg = VALUE #( ( `TICK` ) ( `2000` ) ) ).
4843
49-
WHEN client->check_on_event( `TIMER_FINISHED` ).
44+
WHEN client->check_on_event( `TICK` ).
5045
counter = counter + 1.
5146
client->view_model_update( ).
47+
client->action( val = client->cs_event-start_timer
48+
t_arg = VALUE #( ( `TICK` ) ( `2000` ) ) ).
5249
5350
ENDCASE.
5451
5552
ENDMETHOD.
5653
ENDCLASS.
5754
```
58-
With `checkrepeat = abap_true`, the timer restarts after each event automatically — no manual restart needed.
55+
56+
The counter increments every 2 seconds. To stop the loop, simply don't re-arm the timer in the handler.
5957

6058
#### One-Shot Timer
6159

62-
For a one-shot fire (e.g., to open a new browser tab), omit `checkrepeat` and control activation via `checkactive`:
60+
A single `start_timer` call fires once — perfect for a deferred action like opening a new tab after a short delay:
6361

6462
```abap
65-
CLASS z2ui5_cl_sample_timer_once DEFINITION PUBLIC.
66-
67-
PUBLIC SECTION.
68-
INTERFACES z2ui5_if_app.
69-
DATA mv_url TYPE string.
70-
DATA mv_check_timer_active TYPE abap_bool.
71-
DATA client TYPE REF TO z2ui5_if_client.
72-
METHODS display_view.
73-
74-
ENDCLASS.
75-
76-
CLASS z2ui5_cl_sample_timer_once IMPLEMENTATION.
77-
78-
METHOD display_view.
79-
80-
DATA(view) = z2ui5_cl_xml_view=>factory( ).
81-
82-
client->view_display( view->shell(
83-
)->page( title = `abap2UI5 - Timer One-Shot`
84-
navbuttonpress = client->_event( `BACK` )
85-
shownavbutton = client->check_app_prev_stack( )
86-
)->_z2ui5( )->timer(
87-
checkactive = client->_bind( mv_check_timer_active )
88-
finished = client->_event_client(
89-
val = client->cs_event-open_new_tab
90-
t_arg = VALUE #( ( `$` && client->_bind( mv_url ) ) ) )
91-
)->simple_form( title = `Form Title`
92-
editable = abap_true
93-
)->content( `form`
94-
)->button(
95-
text = `open new tab`
96-
press = client->_event( `BUTTON_OPEN_NEW_TAB` )
97-
)->stringify( ) ).
98-
99-
ENDMETHOD.
100-
101-
METHOD z2ui5_if_app~main.
102-
103-
me->client = client.
104-
105-
IF client->check_on_init( ).
106-
mv_check_timer_active = abap_false.
107-
display_view( ).
108-
ENDIF.
109-
110-
CASE client->get( )-event.
111-
112-
WHEN `BUTTON_OPEN_NEW_TAB`.
113-
mv_check_timer_active = abap_true.
114-
mv_url = `https://www.google.com/search?q=abap2ui5`.
115-
client->view_model_update( ).
116-
117-
WHEN `BACK`.
118-
client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ).
63+
WHEN client->check_on_event( `BUTTON_OPEN_NEW_TAB` ).
64+
client->action( val = client->cs_event-start_timer
65+
t_arg = VALUE #( ( `FIRE_OPEN_TAB` ) ( `500` ) ) ).
11966
120-
ENDCASE.
121-
122-
ENDMETHOD.
123-
ENDCLASS.
67+
WHEN client->check_on_event( `FIRE_OPEN_TAB` ).
68+
client->action( val = client->cs_event-open_new_tab
69+
t_arg = VALUE #( ( `https://www.google.com/search?q=abap2ui5` ) ) ).
12470
```
125-
The timer starts inactive. When the user clicks the button, the handler sets `mv_check_timer_active` to `abap_true` and the timer fires once, opening a new browser tab via `_event_client`.
12671

127-
#### Stopping a Repeating Timer
72+
#### Replacing a Pending Timer
12873

129-
To stop a repeating timer, set the bound `checkactive` flag to `abap_false`:
130-
131-
```abap
132-
WHEN client->check_on_event( `TOGGLE_TIMER` ).
133-
IF check_timer_active = abap_true.
134-
check_timer_active = abap_false.
135-
ELSE.
136-
check_timer_active = abap_true.
137-
ENDIF.
138-
client->view_model_update( ).
139-
```
74+
There is one timer at a time. Calling `start_timer` again before the previous one fires replaces it — useful for a debounce, e.g. auto-saving an input field 500 ms after the last keystroke.
14075

14176
::: warning
142-
Each timer event causes a full backend roundtrip. Use sensible intervals (e.g., 2000ms or more) to avoid heavy server load.
77+
Each timer tick causes a full backend roundtrip. Use sensible intervals (e.g. 2000 ms or more) to avoid heavy server load.
14378
:::

docs/cookbook/browser_interaction/title.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ outline: [2, 4]
33
---
44
# Title
55

6-
Set the text the browser shows in the tab and window title bar. abap2UI5 offers a static option via the user-exit configuration, and a dynamic option via a follow-up JavaScript action.
6+
Set the text the browser shows in the tab and window title bar. abap2UI5 offers a static option via the user-exit configuration, and a dynamic option via the `action` method.
77

88
#### Static — via User Exit
99

@@ -19,7 +19,7 @@ ENDMETHOD.
1919

2020
#### Dynamic — at Runtime
2121

22-
To change the title after the app is running — for example, to reflect the current record — push a follow-up action that updates `document.title` directly:
22+
To change the title after the app is running — for example, to reflect the current record — call the `set_title` frontend event from the backend:
2323

2424
```abap
2525
METHOD z2ui5_if_app~main.
@@ -35,9 +35,13 @@ METHOD z2ui5_if_app~main.
3535
)->stringify( ) ).
3636
3737
WHEN client->check_on_event( `RENAME` ).
38-
client->follow_up_action( `document.title = "Invoice 4711";` ).
38+
client->action(
39+
val = client->cs_event-set_title
40+
t_arg = VALUE #( ( `Invoice 4711` ) ) ).
3941
4042
ENDCASE.
4143
4244
ENDMETHOD.
4345
```
46+
47+
Inside an SAP Fiori Launchpad shell the title is forwarded to the `ShellUIService`; standalone the framework falls back to `document.title`.

0 commit comments

Comments
 (0)