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: 24 additions & 22 deletions docs/.vitepress/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export default defineConfig({
// The section is called Getting Started in the sidebar this opens;
// "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: "Tutorial", link: "/tutorials/overview" }, // nav
{ 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
Expand Down Expand Up @@ -179,7 +179,7 @@ export default defineConfig({
link: "/get_started/about",
collapsed: true,
items: [
{ text: "Introduction", link: "/get_started/about" }, // sidebar
{ text: "In a Nutshell", 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
Expand All @@ -190,48 +190,45 @@ export default defineConfig({
{ text: "Hello World", link: "/get_started/hello_world" },
],
},
{ text: "Tooling", link: "/get_started/tooling" },
{ text: "Building with AI", link: "/get_started/ai" },
{ text: "Developing with AI", link: "/get_started/ai" },
{ text: `What's Next?`, link: "/get_started/next" },
],
},
{
// Between Getting Started and the Cookbook on purpose: a tutorial is
// read after the framework is installed and before the reference
// chapters, and that is the order the three sections stand in.
text: "Tutorials",
text: "Tutorial",
link: "/tutorials/overview",
collapsed: true,
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.
// No `collapsed` key at all, like Quickstart above: that is what
// makes a group a plain labelled list instead of a collapsible
// one. `collapsed: false` would still render the toggle and still
// let the steps be folded away - and the sequence IS the tutorial,
// so a reader working through it has to see where they are on
// every page.
text: "Walkthrough",
link: "/tutorials/walkthrough/overview",
collapsed: false,
items: [
{ text: "Introduction", link: "/tutorials/walkthrough/overview" }, // sidebar
{ text: "1. Hello World", link: "/tutorials/walkthrough/step-1" },
{ text: "1. The App Class", 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: "8. Selection Screen", link: "/tutorials/walkthrough/step-8" },
{ text: "9. Tables", link: "/tutorials/walkthrough/step-9" },
{ text: "10. App Structure", link: "/tutorials/walkthrough/step-10" },
],
},
// 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" },
// The sheet you keep open WHILE working through the steps. It keeps
// the URL it was published under - only the entry that navigates to
// it moved out of the Cookbook, and it is not listed twice: an entry
// standing in two sidebar sections makes its own search results
// ambiguous.
{ text: "Cheat Sheet", link: "/cookbook/cheat_sheet" },
],
},
Expand Down Expand Up @@ -517,6 +514,11 @@ export default defineConfig({
text: "Developer Setup",
collapsed: true,
items: [
// Moved out of Getting Started: which editor, transpiler and
// client tools you develop WITH is a question a newcomer does
// not have yet, and on the entry path it read as a required
// step. It belongs next to the local setup it describes.
{ text: "Tooling", link: "/get_started/tooling" },
{ text: "Local Setup", link: "/advanced/local" },
{
text: "Project Tools",
Expand Down
2 changes: 1 addition & 1 deletion docs/.vitepress/playground.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const NEEDS_MORE_THAN_A_BROWSER = [
* ABAP with its comments taken out and its text blanked, so a rule can only be
* tripped by code. Both halves were put here by a false positive:
*
* - `get_started/full_example.md` shows the SELECT a reader would write, as a
* - `tutorials/walkthrough/step-10.md` shows the SELECT a reader would write, as a
* comment, above the demo data it uses instead — and it runs perfectly
* well.
* - `clipboard.md` says `mv_text = \`Hello from abap2UI5\``, and a rule
Expand Down
6 changes: 3 additions & 3 deletions docs/cookbook/event_navigation/life_cycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ CLASS z2ui5_cl_demo_app_001 IMPLEMENTATION.
ENDCLASS.
```

Whether you dispatch with `CASE abap_true` (as above) or with an equivalent `IF` / `ELSEIF` chain (as the [Hello World](/get_started/hello_world) and [Full Example](/get_started/full_example) tutorials do) is a matter of taste — the structure is what counts. Three things make this the recommended shape:
Whether you dispatch with `CASE abap_true` (as above) or with an equivalent `IF` / `ELSEIF` chain (as the [Hello World](/get_started/hello_world) page and the first steps of the [Walkthrough](/tutorials/overview) do) is a matter of taste — the structure is what counts. Three things make this the recommended shape:

1. **Store `client` on `me->client`** so handler methods can use it without passing it around.
2. **Dispatch by event name** — `` check_on_event( `POST` ) `` rather than a generic `` CASE client->get( )-event `` with a second dispatch level. Each event gets its own `WHEN`. (With many events or extracted handler methods, the `CASE client->get( )-event` form is a fine alternative — the [Full Example](/get_started/full_example) uses it.)
2. **Dispatch by event name** — `` check_on_event( `POST` ) `` rather than a generic `` CASE client->get( )-event `` with a second dispatch level. Each event gets its own `WHEN`. (With many events or extracted handler methods, the `CASE client->get( )-event` form is a fine alternative — the walkthrough's [last step](/tutorials/walkthrough/step-10) uses it.)
3. **One render method per view** — call it from any `WHEN` that should rebuild the screen (`check_on_init`, after a search, after a navigation return). Event handlers that only mutate state and reuse the existing view (a button press inside a popup, a toast) skip it — see [The View Is Only Sent When You Call `view_display`](#the-view-is-only-sent-when-you-call-view-display) below.

For a tiny app with one or two events, inline the view and the handler directly in the `WHEN` branches and skip the handler methods entirely. [Hello World](/get_started/hello_world) shows this variant; [Full Example](/get_started/full_example) shows the full version with multiple handler methods, a popup, and persistence. Both follow the same pattern — only the amount of code inside each branch differs.
For a tiny app with one or two events, inline the view and the handler directly in the `WHEN` branches and skip the handler methods entirely. [Hello World](/get_started/hello_world) shows this variant; the walkthrough's [last step](/tutorials/walkthrough/step-10) shows the full version with multiple handler methods, a popup, and persistence. Both follow the same pattern — only the amount of code inside each branch differs.

## Lifecycle Pitfalls

Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/troubleshooting/common_failures.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Where to look:
- **Symptom**: a button on the main page "does nothing" right after a popup workflow, or a second open reopens the same popup on top of the first.
- **Pair every `popup_display( )` with an explicit `popup_destroy( )`** in **every** branch that ends the dialog — Save and Cancel both need it, not just the happy path.

See [Popup](/cookbook/popup_popover/popup) and the worked example in [Full Example](/get_started/full_example).
See [Popup](/cookbook/popup_popover/popup) and the worked example in the walkthrough's [Popups step](/tutorials/walkthrough/step-7).

## Event-Name Casing Mismatch

Expand Down
2 changes: 1 addition & 1 deletion docs/get_started/about.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
outline: [2, 4]
---
# Introduction
# In a Nutshell

**Build UI5 Apps Purely in ABAP**

Expand Down
50 changes: 31 additions & 19 deletions docs/get_started/ai.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,46 @@
---
outline: [2, 4]
---
# Building with AI

An AI assistant writing abap2UI5 starts at a disadvantage nothing about your
project causes. Almost every abap2UI5 example on the public web builds its view
with `z2ui5_cl_xml_view`, the frozen predecessor of
`z2ui5_cl_ui5_view_builder` — so that is what a model writes when asked for an
app, confidently, and in an API that is no longer the one to use.

Everything below is a way of telling it otherwise, in rising order of effort.
# Developing with AI

abap2UI5 is unusually well suited to being written by an AI assistant, and the
reason is structural rather than lucky:

- **An app is one ABAP class — source code, and nothing else.** No service to
generate, no OData artifacts, no frontend project, no manifest, no
deployment pipeline. There is exactly one file for an agent to write, and
the thing it writes is the thing that runs.
- **The whole app is text.** View, logic, state and data flow live in the same
class, in one language. An agent never has to keep an ABAP backend and a
JavaScript frontend in step, because there is no second half to drift.
- **There are hundreds of working examples to learn from.** The three sample
catalogues hold complete, tested apps — one per pattern, every one linted and
rendered — so "has somebody already built a value help, a tree, navigation
between two apps?" is a question with a real answer instead of a guess.
- **The result can be checked without an SAP system.** The
[abap2UI5 linter](/advanced/linter) reconstructs the UI5 view out of the ABAP
that builds it and reports what UI5 does not have. An agent that can verify
its own work stops handing you apps that do not render.

Everything below turns those properties into a setup, in rising order of
effort. Start at the top; each level is useful on its own.

## Paste the essentials

The zero-setup version, for any assistant with web access: paste this ahead of
your task. It corrects the four things a model most reliably gets wrong about
abap2UI5:
your task.

```text
Before writing any abap2UI5 code, read https://abap2ui5.github.io/docs/llms.txt
and follow it to the pages you need.

Four things that override whatever you remember about abap2UI5:
The shape of an abap2UI5 app:
1. An app is ONE ABAP class implementing z2ui5_if_app. Everything enters main( ),
which dispatches on client->check_on_navigated( ) (the display branch, true on
first start too), client->check_on_event( `X` ) and - for one-time setup only -
client->check_on_init( ).
2. Build the view with z2ui5_cl_ui5_view_builder and its verbs ele / tag / a / end /
stringify. z2ui5_cl_xml_view is the FROZEN predecessor - it is what most examples
online show, and it is not what to write.
stringify.
3. Bind with client->_bind( ). It is bidirectional; only what the user edited comes back.
4. Every roundtrip is a fresh ABAP session. Nothing survives on the server except
the app class itself, which is serialized.
Expand All @@ -51,9 +63,9 @@ questions:
| [`abap2ui5.github.io/docs/llms.txt`](https://abap2ui5.github.io/docs/llms.txt) | the map of the **prose** — every chapter of this site with one line of what it covers, and [`llms-full.txt`](https://abap2ui5.github.io/docs/llms-full.txt) for all of it in one fetch |
| [`github.com/abap2UI5/abap2UI5/llms.txt`](https://github.com/abap2UI5/abap2UI5/blob/main/llms.txt) | the map of the **code** — the interface files to read instead of guessing at a signature, and the guide for building apps that ships with the framework |

Both are short and both are free to give an assistant that has web access. It
is the cheapest correction available: an agent that has read either one does
not reach for the frozen builder.
Both are short and both are free to give an assistant that has web access.
This is the cheapest step on the page: an agent that has read either one is
working from what abap2UI5 is today rather than from what it recalls.

## Put the conventions in the repository

Expand All @@ -79,8 +91,8 @@ npm run check

The [abap2UI5 linter](/advanced/linter) half is the one that matters
here: it reconstructs the view from the builder chain and reports the names UI5
does not have, the bindings that point at nothing — and a class still built on
the frozen builder.
does not have, the properties that do not exist on the release you target, and
the bindings that point at nothing.

## Give it the loop

Expand Down
Loading