Skip to content

Commit 7ac246c

Browse files
authored
Merge branch 'main' into claude/wizardly-mccarthy-bqrgx
2 parents 865b2da + d5db4a2 commit 7ac246c

1 file changed

Lines changed: 6 additions & 247 deletions

File tree

docs/get_started/full_example.md

Lines changed: 6 additions & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -15,256 +15,15 @@ The example uses sales-order-like data but keeps the SELECTs and updates as plai
1515
4. **Popup** — open a dialog that lets the user change the delivery date.
1616
5. **Post** — confirm in the popup, write the change back, refresh the table.
1717

18-
## The Class Definition
18+
## Tutorial
1919

20-
The controller holds all state in **public** attributes so binding works (see [Lifecycle Pitfalls](/cookbook/event_navigation/life_cycle#lifecycle-pitfalls)). The handler methods are protected — they are called from `main` and never bound.
21-
22-
```abap
23-
CLASS z2ui5_cl_demo_full_example DEFINITION PUBLIC.
24-
25-
PUBLIC SECTION.
26-
INTERFACES z2ui5_if_app.
27-
28-
TYPES:
29-
BEGIN OF ty_row,
30-
order_id TYPE c LENGTH 10,
31-
customer TYPE c LENGTH 10,
32-
material TYPE c LENGTH 18,
33-
quantity TYPE i,
34-
delivery_date TYPE d,
35-
END OF ty_row.
36-
37-
" Selection screen
38-
DATA date_from TYPE d.
39-
DATA date_to TYPE d.
40-
DATA customer TYPE c LENGTH 10.
41-
42-
" Result set
43-
DATA orders TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
44-
45-
" Edit buffer (used by the popup)
46-
DATA edit_row TYPE ty_row.
47-
DATA edit_index TYPE i.
48-
49-
PROTECTED SECTION.
50-
DATA client TYPE REF TO z2ui5_if_client.
51-
52-
METHODS render_main.
53-
METHODS open_edit_popup.
54-
METHODS read_data.
55-
METHODS save_changes.
56-
57-
ENDCLASS.
58-
```
59-
60-
## The `main` Dispatcher
61-
62-
`main` is the only entry point. It uses `CASE abap_true` to dispatch between init, events, and navigation returns — the standard [life-cycle pattern](/cookbook/event_navigation/life_cycle):
63-
64-
```abap
65-
CLASS z2ui5_cl_demo_full_example IMPLEMENTATION.
66-
67-
METHOD z2ui5_if_app~main.
68-
69-
me->client = client.
70-
71-
CASE abap_true.
72-
73-
WHEN client->check_on_init( ).
74-
" preset the selection screen with a useful default
75-
date_from = sy-datum - 30.
76-
date_to = sy-datum.
77-
render_main( ).
78-
79-
WHEN client->check_on_event( `SEARCH` ).
80-
read_data( ).
81-
render_main( ).
82-
83-
WHEN client->check_on_event( `EDIT` ).
84-
open_edit_popup( ).
85-
86-
WHEN client->check_on_event( `SAVE` ).
87-
save_changes( ).
88-
client->popup_destroy( ).
89-
90-
WHEN client->check_on_event( `CANCEL` ).
91-
client->popup_destroy( ).
92-
93-
ENDCASE.
94-
95-
ENDMETHOD.
96-
```
97-
98-
A few things worth noting:
99-
100-
- The view is rebuilt and re-sent in `render_main( )` on the events that change the visible structure (initial render, after the search). On `EDIT`, `SAVE`, and `CANCEL` we only open or close a popup — the underlying view stays.
101-
- Public attributes (`date_from`, `customer`, `orders`, …) carry the state across roundtrips. The framework serializes them between requests automatically.
102-
- Two-way-bound inputs (`_bind_edit`) write user changes back into the public attributes *before* the event handler runs.
103-
104-
## The Selection Screen and the Table
105-
106-
`render_main` paints the selection panel and, if `orders` already has rows, the result table below it. The two parts live in the same `Page`:
107-
108-
```abap
109-
METHOD render_main.
110-
111-
DATA(view) = z2ui5_cl_xml_view=>factory( ).
112-
DATA(page) = view->shell( )->page( title = `Sales Orders` ).
113-
114-
" --- Selection screen -------------------------------------------------
115-
DATA(form) = page->simple_form( title = `Selection` editable = abap_true
116-
)->content( `f` ).
117-
form->label( `Date from` )->date_picker( client->_bind_edit( date_from ) ).
118-
form->label( `Date to` )->date_picker( client->_bind_edit( date_to ) ).
119-
form->label( `Customer` )->input( client->_bind_edit( customer ) ).
120-
form->button( text = `Search`
121-
type = `Emphasized`
122-
press = client->_event( `SEARCH` ) ).
123-
124-
" --- Result table -----------------------------------------------------
125-
IF orders IS NOT INITIAL.
126-
DATA(tab) = page->table(
127-
items = client->_bind( orders )
128-
headerText = `Results` ).
129-
tab->columns(
130-
)->column( )->text( `Order` )->get_parent(
131-
)->column( )->text( `Customer` )->get_parent(
132-
)->column( )->text( `Material` )->get_parent(
133-
)->column( )->text( `Quantity` )->get_parent(
134-
)->column( )->text( `Delivery Date` )->get_parent(
135-
)->column( )->text( `` ).
136-
DATA(cells) = tab->items( )->column_list_item( )->cells( ).
137-
cells->text( `{ORDER_ID}` ).
138-
cells->text( `{CUSTOMER}` ).
139-
cells->text( `{MATERIAL}` ).
140-
cells->text( `{QUANTITY}` ).
141-
cells->text( `{DELIVERY_DATE}` ).
142-
cells->button( text = `Edit`
143-
press = client->_event(
144-
val = `EDIT`
145-
t_arg = VALUE #( ( `${ORDER_ID}` ) ) ) ).
146-
ENDIF.
147-
148-
client->view_display( view->stringify( ) ).
149-
150-
ENDMETHOD.
151-
```
152-
153-
The `Edit` button passes the bound row's `ORDER_ID` as an event argument. On the next roundtrip, the handler reads it via `client->get_event_arg( 1 )` to know which row was clicked.
154-
155-
## Reading Data
156-
157-
`read_data` is plain ABAP — replace the dummy fill with a real `SELECT` against your tables. The framework does not get in the way here:
158-
159-
```abap
160-
METHOD read_data.
161-
162-
CLEAR orders.
163-
164-
" Replace with your own SELECT, e.g.:
165-
"
166-
" SELECT vbeln AS order_id, kunnr AS customer,
167-
" matnr AS material, kwmeng AS quantity, edatu AS delivery_date
168-
" FROM vbap
169-
" INNER JOIN vbak ON vbap~vbeln = vbak~vbeln
170-
" WHERE vbak~erdat BETWEEN @date_from AND @date_to
171-
" AND ( @customer IS INITIAL OR vbak~kunnr = @customer )
172-
" INTO TABLE @orders.
173-
174-
" Dummy data so the tutorial runs without a database table:
175-
orders = VALUE #(
176-
( order_id = `0000010001` customer = `1000` material = `M-01`
177-
quantity = 5 delivery_date = sy-datum + 7 )
178-
( order_id = `0000010002` customer = `1000` material = `M-02`
179-
quantity = 12 delivery_date = sy-datum + 14 )
180-
( order_id = `0000010003` customer = `1010` material = `M-03`
181-
quantity = 1 delivery_date = sy-datum + 3 ) ).
182-
183-
ENDMETHOD.
184-
```
185-
186-
## The Edit Popup
187-
188-
When the user presses `Edit`, the handler picks the row out of `orders`, stores it in `edit_row`, and renders a popup with two-way-bound fields. Because `edit_row` is a public attribute, anything the user types ends up there before `SAVE` runs:
189-
190-
```abap
191-
METHOD open_edit_popup.
192-
193-
DATA(order_id) = client->get_event_arg( 1 ).
194-
READ TABLE orders WITH KEY order_id = order_id
195-
ASSIGNING FIELD-SYMBOL(<row>).
196-
IF sy-subrc <> 0.
197-
client->message_box_display(
198-
text = |Order { order_id } not found| type = `error` ).
199-
RETURN.
200-
ENDIF.
201-
202-
edit_row = <row>.
203-
edit_index = sy-tabix.
204-
205-
DATA(popup) = z2ui5_cl_xml_view=>factory_popup( ).
206-
DATA(dlg) = popup->dialog(
207-
title = |Edit Order { edit_row-order_id }|
208-
contentWidth = `400px` ).
209-
210-
DATA(form) = dlg->simple_form( editable = abap_true )->content( `f` ).
211-
form->label( `Customer` )->text( client->_bind( edit_row-customer ) ).
212-
form->label( `Material` )->text( client->_bind( edit_row-material ) ).
213-
form->label( `Quantity` )->input( client->_bind_edit( edit_row-quantity ) ).
214-
form->label( `Delivery Date` )->date_picker( client->_bind_edit( edit_row-delivery_date ) ).
215-
216-
dlg->buttons(
217-
)->button( text = `Save`
218-
type = `Emphasized`
219-
press = client->_event( `SAVE` )
220-
)->button( text = `Cancel`
221-
press = client->_event( `CANCEL` ) ).
222-
223-
client->popup_display( popup->stringify( ) ).
224-
225-
ENDMETHOD.
226-
```
227-
228-
Note that **the same** `client->view_display` from `render_main` is still active behind the popup. UI5 dims the page and overlays the dialog — there is no second view to manage.
229-
230-
## Posting the Changes
231-
232-
`save_changes` writes `edit_row` back into the `orders` table at the position captured when the popup opened, then runs whatever persistence you need. In a real app this is the place to call `UPDATE vbap …` or trigger a BAPI:
233-
234-
```abap
235-
METHOD save_changes.
236-
237-
READ TABLE orders INDEX edit_index ASSIGNING FIELD-SYMBOL(<row>).
238-
IF sy-subrc <> 0.
239-
client->message_box_display(
240-
text = `Row no longer exists — please search again` type = `error` ).
241-
RETURN.
242-
ENDIF.
243-
244-
<row> = edit_row.
245-
246-
" Persistence — replace with your real update / BAPI / EML call:
247-
"
248-
" UPDATE vbap
249-
" SET kwmeng = @edit_row-quantity, edatu = @edit_row-delivery_date
250-
" WHERE vbeln = @edit_row-order_id.
251-
" COMMIT WORK.
252-
253-
client->message_toast_display(
254-
|Order { edit_row-order_id } updated| ).
255-
256-
ENDMETHOD.
257-
258-
ENDCLASS.
259-
```
260-
261-
When `save_changes` returns, `main` calls `client->popup_destroy( )` to close the dialog. The table on the main view updates automatically because UI5 keeps reading from the same model path — the framework re-serializes `orders` on every response, so the edited row appears with its new values without a second `view_display( )` call.
20+
🚧 UNDER CONSTRUCTION 🚧
26221

26322
## What to Take Away
26423

265-
- One controller class, one `main` method, all state in public attributes — that is the whole app.
266-
- The view tree is rebuilt only when the structure changes. Edits, saves, and popup open/close do not need a fresh `view_display( )`.
267-
- Popups are just a different factory (`factory_popup`) on the same `z2ui5_cl_xml_view`, displayed via `popup_display` / `popup_destroy` while the main view stays in place.
268-
- Reading and writing the database is plain ABAP — abap2UI5 does not abstract that layer, which is what makes it easy to plug into existing code.
24+
- One controller class, one `main` method, all state in public attributes — that is the whole app
25+
- The view is rebuilt only when the structure changes. Edits, saves, and popup open/close do not need a fresh `view_display( )`
26+
- Popups are just a different factory (`factory_popup`) on the same `z2ui5_cl_xml_view`, displayed via `popup_display` / `popup_destroy` while the main view stays in place
27+
- Reading and writing the database is plain ABAP — abap2UI5 does not abstract that layer, which is what makes it easy to plug into existing code
26928

27029
From here, look at the [Cookbook](/cookbook/event_navigation/life_cycle) for value helps, navigation between apps, message handling, and other patterns you will need next.

0 commit comments

Comments
 (0)