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
46 changes: 32 additions & 14 deletions docs/.vitepress/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default defineConfig({
// "Introduction" was the first PAGE in it, one level down.
{ text: "Getting Started", link: "/get_started/about" }, // nav
{ text: "Tutorials", link: "/tutorials/overview" }, // nav
{ text: "Cookbook", link: "/cookbook/overview" },
{ text: "Cookbook", link: "/cookbook/view/definition" },
{ text: "Configuration", link: "/configuration/setup" },
// Technical Insight is not a line of its own here any more: it is a
// subsection of Advanced Topic in the sidebar, and a flat dropdown
Expand Down Expand Up @@ -181,11 +181,13 @@ export default defineConfig({
items: [
{ text: "Introduction", link: "/get_started/about" }, // sidebar
{
// Install it, and see one app run. The step-by-step tutorials -
// Full Example among them - are a section of their own now; what
// stays here is the shortest path from nothing to a running app.
text: "Quickstart",
items: [
{ text: "Install with abapGit", link: "/get_started/quickstart" },
{ text: "Hello World", link: "/get_started/hello_world" },
{ text: "Full Example", link: "/get_started/full_example" },
],
},
{ text: "Tooling", link: "/get_started/tooling" },
Expand All @@ -203,30 +205,46 @@ export default defineConfig({
items: [
{ text: "Overview", link: "/tutorials/overview" }, // sidebar
{
// NOT collapsed: the eight steps are the section's content, and a
// reader who is working through them needs to see where they are
// in the sequence on every page. A tutorial whose steps are behind
// one more click reads as a single page that happens to be long.
text: "Walkthrough",
link: "/tutorials/walkthrough/overview",
collapsed: true,
collapsed: false,
items: [
{ text: "Introduction", link: "/tutorials/walkthrough/overview" }, // sidebar
{ text: "1 Hello World", link: "/tutorials/walkthrough/step-1" },
{ text: "2 A First View", link: "/tutorials/walkthrough/step-2" },
{ text: "3 Events", link: "/tutorials/walkthrough/step-3" },
{ text: "4 Data Binding", link: "/tutorials/walkthrough/step-4" },
{ text: "5 List Binding", link: "/tutorials/walkthrough/step-5" },
{ text: "6 Row Events", link: "/tutorials/walkthrough/step-6" },
{ text: "7 Popups", link: "/tutorials/walkthrough/step-7" },
{ text: "8 App Structure", link: "/tutorials/walkthrough/step-8" },
{ text: "1. Hello World", link: "/tutorials/walkthrough/step-1" },
{ text: "2. A First View", link: "/tutorials/walkthrough/step-2" },
{ text: "3. Events", link: "/tutorials/walkthrough/step-3" },
{ text: "4. Data Binding", link: "/tutorials/walkthrough/step-4" },
{ text: "5. List Binding", link: "/tutorials/walkthrough/step-5" },
{ text: "6. Row Events", link: "/tutorials/walkthrough/step-6" },
{ text: "7. Popups", link: "/tutorials/walkthrough/step-7" },
{ text: "8. App Structure", link: "/tutorials/walkthrough/step-8" },
],
},
// Both keep the URL they were published under - only the entry that
// navigates to them moved. Full Example is a step-by-step tutorial
// ("Step 1" to "Step 5") and was the second half of a Quickstart
// group that no longer had a tutorial section to hand it to; the
// Cheat Sheet is the sheet you keep open WHILE working through one.
// Neither is listed twice: an entry standing in two sidebar sections
// makes its own search results ambiguous.
{ text: "Full Example", link: "/get_started/full_example" },
{ text: "Cheat Sheet", link: "/cookbook/cheat_sheet" },
],
},
{
// No overview page any more. This is a collection of concrete
// problem-and-solution chapters, and a map page in front of it was a
// stop between the reader and the recipe - it restated the sidebar
// they were already looking at. The section opens on the first
// chapter instead.
text: "Cookbook",
link: "/cookbook/overview",
link: "/cookbook/view/definition",
collapsed: true,
items: [
{ text: "Overview", link: "/cookbook/overview" },
{ text: "Cheat Sheet", link: "/cookbook/cheat_sheet" },
{
text: "View",
link: "/cookbook/view/definition",
Expand Down
1 change: 0 additions & 1 deletion docs/cookbook/cheat_sheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,4 @@ Any expression that yields a flag works in `b`, so there is no reason to convert

## Next Steps

- [Overview](/cookbook/overview) — the full map of cookbook topics
- [Common Failures](/cookbook/troubleshooting/common_failures) — symptoms and their usual causes
49 changes: 0 additions & 49 deletions docs/cookbook/overview.md

This file was deleted.

180 changes: 8 additions & 172 deletions docs/get_started/hello_world.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,185 +19,21 @@ CLASS zcl_app_hello_world IMPLEMENTATION.
ENDMETHOD.
ENDCLASS.
```

Open the abap2UI5 startup page in your browser (the same page as in the [Quickstart](/get_started/quickstart)), enter the class name `ZCL_APP_HELLO_WORLD` in the input field, and launch your app.

That is a complete abap2UI5 app: one class, one method, no frontend project and no OData service.

::: tip **ABAP Language Versions**
While the HTTP handler has to distinguish between Standard ABAP and ABAP for Cloud, the apps themselves are independent. You're free to choose whether to build your apps with ABAP Cloud compatibility.
:::

### How Apps Work
abap2UI5 follows a thin-frontend model: the browser only renders UI5 views, while all logic, state, and data handling stay in ABAP on the server. Three ideas to keep in mind before writing code:

- **One method, many calls.** The framework calls your app's `main` method on every roundtrip — on the initial start *and* after every user interaction (button press, input change, navigation).
- **State lives in your class.** Public attributes of your app class hold data between roundtrips; abap2UI5 serializes and restores them for you, so you don't manage sessions manually.
- **The `client` object is your only API.** Use it to display views, check which event fired, bind attributes to UI5 controls, and trigger navigation.

Every abap2UI5 app implements the `z2ui5_if_app` interface. It has a single method, `main`, with one parameter: `client` of type `z2ui5_if_client`. (The real interface also declares a few attributes that the framework manages for you — you can ignore them.)
```abap
INTERFACE z2ui5_if_app PUBLIC.
METHODS main
IMPORTING
client TYPE REF TO z2ui5_if_client.
ENDINTERFACE.
```

→ *For a deeper look at the lifecycle and framework internals, see [How It All Works](/technical/how_it_all_works) and [Concept](/technical/concept).*

### View Display
Instead of a message box, let's render a view with some text:
```abap
CLASS zcl_app_hello_world DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
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( `Shell`
)->ele( `Page`
)->a( n = `title` v = `abap2UI5 - Hello World`

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

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

ENDMETHOD.
ENDCLASS.
```

You are writing a UI5 XML view, one control per call. `z2ui5_cl_ui5_view_builder`
has four verbs and no list of controls to look up — every UI5 control,
property and aggregation is available because the builder never knew any of
them by name:

| | |
| --- | --- |
| `ele( )` | add a control and **descend** into it — for a container |
| `tag( )` | add a control and **stay** — for a leaf |
| `a( )` | set **one** attribute on the control the chain is pointing at |
| `end( )` | ascend to the parent |

The single rule: `a( )` applies to the control the chain currently points at,
so attributes follow their control — and a control gets them *before* its
first child. The root `mvc:View` and its `xmlns` declarations are written by
hand, exactly as in a real UI5 view. A trailing `end( )` can be left out:
`stringify( )` renders from the root wherever the chain stopped.

### Events
Now add a button and react to its press event:
```abap
CLASS zcl_app_hello_world DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
ENDCLASS.

CLASS zcl_app_hello_world IMPLEMENTATION.
METHOD z2ui5_if_app~main.

IF client->check_on_navigated( ).

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( `Shell`
)->ele( `Page`
)->a( n = `title` v = `abap2UI5 - Hello World`

)->tag( `Text`
)->a( n = `text` v = `My Text`
)->tag( `Button`
)->a( n = `text` v = `post`
)->a( n = `press` v = client->_event( `POST` ) ).

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

ELSEIF client->check_on_event( `POST` ).

client->message_box_display( `Hello World!` ).

ENDIF.

ENDMETHOD.
ENDCLASS.
```

As introduced above, the framework calls `main` on every roundtrip. The diagram shows both phases — the initial load and a later user event:

```text
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Browser │──────>│ main() │──────>│ Browser │
│ (Start) │ HTTP │ init │ HTTP │ (View) │
└──────────┘ └──────────┘ └────┬─────┘
│ user clicks
┌──────────┐ ┌──────────┐ ┌────┴─────┐
│ Browser │<──────│ main() │<──────│ Browser │
│ (Update) │ HTTP │ event │ HTTP │ (Event) │
└──────────┘ └──────────┘ └──────────┘
```

Use the lifecycle checks to tell these phases apart:

- `client->check_on_init( )` — first call when the app starts
- `client->check_on_event( )` — user triggered an event (e.g. a button press)

Each `check_*` method returns `abap_true` only for its own phase, so the `IF`/`ELSEIF` chain acts as a dispatcher.

### Data Flow
Finally, add a public attribute and bind it to an input field to send data back to the server. The attribute must be in the `PUBLIC SECTION` — the framework accesses it dynamically and silently ignores private or protected attributes (full rules on the [Binding](/cookbook/model/binding) page):
```abap
CLASS zcl_app_hello_world DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
DATA name TYPE string.
ENDCLASS.

CLASS zcl_app_hello_world IMPLEMENTATION.
METHOD z2ui5_if_app~main.

IF client->check_on_navigated( ).

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( `Shell`
)->ele( `Page`
)->a( n = `title` v = `abap2UI5 - Hello World`

)->tag( `Text`
)->a( n = `text` v = `My Text`
)->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( ) ).

ELSEIF client->check_on_event( `POST` ).

client->message_box_display( |Your name is { name }.| ).

ENDIF.

ENDMETHOD.
ENDCLASS.
```
That's all you need. Set a breakpoint to watch the communication and data updates in action, then try changing the view, events, and data flow.
## Next: Build Something

### Jump into the Code
Press `Ctrl+F12` in any running app to open the **Developer Tools** — tabs for the app's source code, the rendered view XML, the model data, the request/response pair and the error log:
![Developer Tools opened with Ctrl+F12 showing code, view, and model](/get_started/image-2.png)
The [Walkthrough](/tutorials/walkthrough/overview) takes this class and grows it
into a small invoice app in eight steps — views, events, data binding, lists and
popups, each step a complete class you can run in the browser. It starts exactly
where this page stops.

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

Expand Down
4 changes: 2 additions & 2 deletions docs/get_started/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ You've installed abap2UI5 and built your first app. From here, pick the directio
## Sample Apps
Hundreds of working apps, and the fastest way to learn abap2UI5 is to read one that already does what you are about to write. They live in three repositories, each with a page that searches it — [**Learn**](https://abap2ui5.github.io/samples/) is the one to start on: the path from the smallest app that runs to files, devices and custom CSS, one idea per sample.

Looking for one in particular? Search the page, or `Ctrl+F` the [catalogue](https://github.com/abap2UI5/samples/blob/main/SAMPLES.md) for `f4`, `tree` or `nav_app_call`. [**Controls**](https://abap2ui5.github.io/samples-controls/) is the UI5 demo kit rebuilt control by control and [**Stack**](https://abap2ui5.github.io/samples-stack/) the samples that need something from your system — each page links the other two at its top. The [Cookbook](/cookbook/overview) links the same apps from the page that explains the pattern.
Looking for one in particular? Search the page, or `Ctrl+F` the [catalogue](https://github.com/abap2UI5/samples/blob/main/SAMPLES.md) for `f4`, `tree` or `nav_app_call`. [**Controls**](https://abap2ui5.github.io/samples-controls/) is the UI5 demo kit rebuilt control by control and [**Stack**](https://abap2ui5.github.io/samples-stack/) the samples that need something from your system — each page links the other two at its top. The [Cookbook](/cookbook/view/definition) links the same apps from the page that explains the pattern.

![Sample apps overview showing tables, lists, trees, and other UI5 controls](/get_started/image-1.png)

Expand All @@ -25,7 +25,7 @@ The samples evolve all the time. Have one to share? Open a PR so others can lear
Optional, and worth the ten minutes: a project [template](/advanced/working_off_stack) with the checks already wired up, a [linter](/advanced/linter) that finds broken views without a system, an [extension](/advanced/vscode) that runs your app on `F9` next to the code, and an [MCP server](/advanced/mcp_server) that lets an AI agent build and *look at* the app. See [Tooling](/get_started/tooling), and [Building with AI](/get_started/ai) if an assistant writes some of it.

## Development
Build views, handle events, share data, and work with tables. The [Cookbook](/cookbook/overview) walks through the patterns you need for everyday work — start with the [Life Cycle](/cookbook/event_navigation/life_cycle) page.
Build views, handle events, share data, and work with tables. The [Cookbook](/cookbook/view/definition) walks through the patterns you need for everyday work — start with the [Life Cycle](/cookbook/event_navigation/life_cycle) page.

## Configuration
Before going live, set up security, performance tuning, Launchpad integration, and more. Start with the [Configuration guide](/configuration/setup).
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ features:
- title: Cookbook
icon: <i class="fa-solid fa-book"></i>
details: Recipes for everyday tasks — views, binding, tables, events, popups, files.
link: /cookbook/overview
link: /cookbook/view/definition
- title: Configuration
icon: <i class="fa-solid fa-gear"></i>
details: Setup, security, performance, launchpad — the road to production use.
Expand Down
Loading
Loading