Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ All serialized files (`.abap`, `.xml`, and any other abapGit-managed file types)
- Classes are **not** `FINAL` — do not add the `FINAL` keyword to class definitions.
- Use `DEFINITION PUBLIC.` — never `DEFINITION PUBLIC CREATE PUBLIC.` (`CREATE PUBLIC` is the default and adds unnecessary overhead).
- Always include `PROTECTED SECTION.` and `PRIVATE SECTION.` in the class definition, even if empty.
- Keep `PRIVATE SECTION.` always empty — declare everything at `PROTECTED SECTION.` level at most.
- In every section (`PUBLIC SECTION.`, `PROTECTED SECTION.`), always follow this declaration order: `TYPES` first, then `DATA`, then `METHODS`.
- **Blank lines — class definition** (`EMPTY_LINES_IN_CLASS_DEFINITION`):
- Add one blank line above each section keyword (`PUBLIC SECTION.`, `PROTECTED SECTION.`, `PRIVATE SECTION.`) — unless the preceding section is empty.
Expand All @@ -58,6 +59,17 @@ All serialized files (`.abap`, `.xml`, and any other abapGit-managed file types)
- Max 1 consecutive blank line inside a method body.
- Always add 1 blank line **before** an `IF` block — **except** when the method is a pure dispatcher (its only purpose is to jump to other methods, with no own logic before the `IF`). In that case, omit the blank line between the opening assignment and the `IF`.
- Always add 1 blank line **before** `ELSEIF` and `ELSE`.
- In setup methods (`on_init` and similar), add 1 blank line between the last data assignment and the first non-assignment statement (e.g. before `view_display( )`):
```abap
METHOD on_init.

price = `1234`.
currency = `EUR`.

view_display( ).

ENDMETHOD.
```
- If a branch (`IF`, `ELSEIF`, `ELSE`) contains **more than one statement**, add 1 blank line directly after the condition line as well:
```abap
me->client = client.
Expand Down Expand Up @@ -264,6 +276,63 @@ Key rules for `z2ui5_cl_util_xml`:
- Only declare namespaces that are actually used in the view
- `stringify()` on the factory root produces the complete XML string

#### Method chaining

Each call in a chain must start on its own line — never place two `->_()` / `->__()` calls on the same line:

```abap
" Wrong
DATA(page) = root->__( `Shell` )->__( n = `Page`

" Correct
DATA(page) = root->__( `Shell`
)->__( n = `Page`
```

Chain continuations (`)->`) are indented 3 spaces relative to the statement's base indentation.

#### Parameter alignment

When `p` appears on a continuation line, align it directly under `n` — one space after the opening `(`:

```abap
" Wrong — p is one space too far right
)->_( n = `Input`
p = VALUE #( ... ) ).

" Correct — p directly under n
)->_( n = `Input`
p = VALUE #( ... ) ).
```

Continuation lines inside `VALUE #( )` align with the first tuple `(`:

```abap
)->_( n = `Input`
p = VALUE #( ( n = `type` v = `Number` )
( n = `value` v = client->_bind_edit( qty ) ) ) ).
```

#### VALUE #( ) formatting

In `VALUE #( )` constructor expressions with named fields, use **either** entirely inline (all fields on one line) **or** each field on its own line — never mix both styles in the same expression:

```abap
" Wrong — mixed
t_products = VALUE #(
( name = `Notebook Basic 15` product_id = `HT-1000` supplier_name = `Very Best Screens`
dimensions = `30 x 18 x 3 cm` weight_measure = `4.2` weight_unit = `KG` ) ).

" Correct — one field per line, = signs aligned
t_products = VALUE #(
( name = `Notebook Basic 15`
product_id = `HT-1000`
supplier_name = `Very Best Screens`
dimensions = `30 x 18 x 3 cm`
weight_measure = `4.2`
weight_unit = `KG` ) ).
```

## App Structure

### Simple apps (< 50 lines in `main`)
Expand Down
78 changes: 50 additions & 28 deletions src/02/z2ui5_cl_demo_app_355.clas.abap
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CLASS z2ui5_cl_demo_app_355 DEFINITION PUBLIC CREATE PUBLIC.
CLASS z2ui5_cl_demo_app_355 DEFINITION PUBLIC.

PUBLIC SECTION.
INTERFACES z2ui5_if_app.
Expand All @@ -13,23 +13,44 @@ CLASS z2ui5_cl_demo_app_355 DEFINITION PUBLIC CREATE PUBLIC.
DATA volume TYPE string.

PROTECTED SECTION.
DATA client TYPE REF TO z2ui5_if_client.

METHODS on_init.
METHODS view_display.

PRIVATE SECTION.
ENDCLASS.


CLASS z2ui5_cl_demo_app_355 IMPLEMENTATION.

METHOD z2ui5_if_app~main.

me->client = client.
IF client->check_on_init( ).
wlan = abap_true.
flight = abap_true.
high_perf = abap_true.
price = `799`.
address = `Main Rd, Manchester`.
country = `GR`.
volume = `7`.
on_init( ).
ENDIF.

ENDMETHOD.


METHOD on_init.

wlan = abap_true.
flight = abap_true.
high_perf = abap_true.
price = `799`.
address = `Main Rd, Manchester`.
country = `GR`.
volume = `7`.

view_display( ).

ENDMETHOD.


METHOD view_display.

DATA(view) = z2ui5_cl_util_xml=>factory( ).
DATA(root) = view->__( n = `View` ns = `mvc`
p = VALUE #( ( n = `displayBlock` v = abap_true )
Expand All @@ -38,16 +59,17 @@ CLASS z2ui5_cl_demo_app_355 IMPLEMENTATION.
( n = `xmlns:core` v = `sap.ui.core` )
( n = `xmlns:mvc` v = `sap.ui.core.mvc` ) ) ).

DATA(page) = root->__( `Shell` )->__( n = `Page`
p = VALUE #( ( n = `navButtonPress` v = client->_event_nav_app_leave( ) )
( n = `showNavButton` v = client->check_app_prev_stack( ) )
( n = `title` v = `abap2UI5 - InputListItem` ) ) ).
DATA(page) = root->__( `Shell`
)->__( n = `Page`
p = VALUE #( ( n = `navButtonPress` v = client->_event_nav_app_leave( ) )
( n = `showNavButton` v = client->check_app_prev_stack( ) )
( n = `title` v = `abap2UI5 - InputListItem` ) ) ).

page->__( `headerContent`
)->_( n = `Link`
p = VALUE #( ( n = `href` v = `https://sapui5.hana.ondemand.com/sdk/#/entity/sap.m.InputListItem/sample/sap.m.sample.InputListItem` )
( n = `target` v = `_blank` )
( n = `text` v = `UI5 Demo Kit` ) ) ).
p = VALUE #( ( n = `href` v = `https://sapui5.hana.ondemand.com/sdk/#/entity/sap.m.InputListItem/sample/sap.m.sample.InputListItem` )
( n = `target` v = `_blank` )
( n = `text` v = `UI5 Demo Kit` ) ) ).

DATA(list) = page->__( n = `List` a = `headerText` v = `Input` ).

Expand All @@ -59,24 +81,24 @@ CLASS z2ui5_cl_demo_app_355 IMPLEMENTATION.

list->__( n = `InputListItem` a = `label` v = `High Performance`
)->_( n = `RadioButton`
p = VALUE #( ( n = `groupName` v = `GroupPerf` )
( n = `selected` v = client->_bind_edit( high_perf ) ) ) ).
p = VALUE #( ( n = `groupName` v = `GroupPerf` )
( n = `selected` v = client->_bind_edit( high_perf ) ) ) ).

list->__( n = `InputListItem` a = `label` v = `Battery Saving`
)->_( n = `RadioButton`
p = VALUE #( ( n = `groupName` v = `GroupPerf` )
( n = `selected` v = client->_bind_edit( battery ) ) ) ).
p = VALUE #( ( n = `groupName` v = `GroupPerf` )
( n = `selected` v = client->_bind_edit( battery ) ) ) ).

list->__( n = `InputListItem` a = `label` v = `Price (EUR)`
)->_( n = `Input`
p = VALUE #( ( n = `placeholder` v = `Price` )
( n = `type` v = `Number` )
( n = `value` v = client->_bind_edit( price ) ) ) ).
p = VALUE #( ( n = `placeholder` v = `Price` )
( n = `type` v = `Number` )
( n = `value` v = client->_bind_edit( price ) ) ) ).

list->__( n = `InputListItem` a = `label` v = `Address`
)->_( n = `Input`
p = VALUE #( ( n = `placeholder` v = `Address` )
( n = `value` v = client->_bind_edit( address ) ) ) ).
p = VALUE #( ( n = `placeholder` v = `Address` )
( n = `value` v = client->_bind_edit( address ) ) ) ).

list->__( n = `InputListItem` a = `label` v = `Country`
)->__( n = `Select` a = `selectedKey` v = client->_bind_edit( country )
Expand All @@ -89,10 +111,10 @@ CLASS z2ui5_cl_demo_app_355 IMPLEMENTATION.
list->__( n = `InputListItem` a = `label` v = `Volume`
)->__( n = `HBox` a = `justifyContent` v = `End`
)->_( n = `Slider`
p = VALUE #( ( n = `max` v = `10` )
( n = `min` v = `0` )
( n = `value` v = client->_bind_edit( volume ) )
( n = `width` v = `200px` ) ) ).
p = VALUE #( ( n = `max` v = `10` )
( n = `min` v = `0` )
( n = `value` v = client->_bind_edit( volume ) )
( n = `width` v = `200px` ) ) ).

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

Expand Down
46 changes: 24 additions & 22 deletions src/02/z2ui5_cl_demo_app_356.clas.abap
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CLASS z2ui5_cl_demo_app_356 DEFINITION PUBLIC CREATE PUBLIC.
CLASS z2ui5_cl_demo_app_356 DEFINITION PUBLIC.

PUBLIC SECTION.
INTERFACES z2ui5_if_app.
Expand All @@ -11,6 +11,7 @@ CLASS z2ui5_cl_demo_app_356 DEFINITION PUBLIC CREATE PUBLIC.
PRIVATE SECTION.
ENDCLASS.


CLASS z2ui5_cl_demo_app_356 IMPLEMENTATION.

METHOD z2ui5_if_app~main.
Expand All @@ -23,41 +24,42 @@ CLASS z2ui5_cl_demo_app_356 IMPLEMENTATION.
( n = `xmlns:l` v = `sap.ui.layout` )
( n = `xmlns:mvc` v = `sap.ui.core.mvc` ) ) ).

DATA(page) = root->__( `Shell` )->__( n = `Page`
p = VALUE #( ( n = `navButtonPress` v = client->_event_nav_app_leave( ) )
( n = `showNavButton` v = client->check_app_prev_stack( ) )
( n = `title` v = `abap2UI5 - Label` ) ) ).
DATA(page) = root->__( `Shell`
)->__( n = `Page`
p = VALUE #( ( n = `navButtonPress` v = client->_event_nav_app_leave( ) )
( n = `showNavButton` v = client->check_app_prev_stack( ) )
( n = `title` v = `abap2UI5 - Label` ) ) ).

page->__( `headerContent`
)->_( n = `Link`
p = VALUE #( ( n = `href` v = `https://ui5.sap.com/sdk/#/entity/sap.m.Label/sample/sap.m.sample.Label` )
( n = `target` v = `_blank` )
( n = `text` v = `UI5 Demo Kit` ) ) ).
p = VALUE #( ( n = `href` v = `https://ui5.sap.com/sdk/#/entity/sap.m.Label/sample/sap.m.sample.Label` )
( n = `target` v = `_blank` )
( n = `text` v = `UI5 Demo Kit` ) ) ).

DATA(layout) = page->__( n = `VerticalLayout` ns = `l`
p = VALUE #( ( n = `class` v = `sapUiContentPadding` )
( n = `width` v = `100%` ) ) ).

layout->_( n = `Label`
p = VALUE #( ( n = `labelFor` v = `input-a` )
( n = `text` v = `Label A (required)` ) )
p = VALUE #( ( n = `labelFor` v = `input-a` )
( n = `text` v = `Label A (required)` ) )
)->_( n = `Input`
p = VALUE #( ( n = `id` v = `input-a` )
( n = `required` v = abap_true )
( n = `value` v = client->_bind_edit( input_a ) ) )
p = VALUE #( ( n = `id` v = `input-a` )
( n = `required` v = abap_true )
( n = `value` v = client->_bind_edit( input_a ) ) )
)->_( n = `Label`
p = VALUE #( ( n = `design` v = `Bold` )
( n = `labelFor` v = `input-b` )
( n = `text` v = `Label B (bold)` ) )
p = VALUE #( ( n = `design` v = `Bold` )
( n = `labelFor` v = `input-b` )
( n = `text` v = `Label B (bold)` ) )
)->_( n = `Input`
p = VALUE #( ( n = `id` v = `input-b` )
( n = `value` v = client->_bind_edit( input_b ) ) )
p = VALUE #( ( n = `id` v = `input-b` )
( n = `value` v = client->_bind_edit( input_b ) ) )
)->_( n = `Label`
p = VALUE #( ( n = `labelFor` v = `input-c` )
( n = `text` v = `Label C (normal)` ) )
p = VALUE #( ( n = `labelFor` v = `input-c` )
( n = `text` v = `Label C (normal)` ) )
)->_( n = `Input`
p = VALUE #( ( n = `id` v = `input-c` )
( n = `value` v = client->_bind_edit( input_c ) ) ) ).
p = VALUE #( ( n = `id` v = `input-c` )
( n = `value` v = client->_bind_edit( input_c ) ) ) ).

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

Expand Down
Loading
Loading