Skip to content

About

Build dynamic, reactive full-stack web applications in 100% pure ABAP with Preact & TailwindCSS on the frontend.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

38 Commits

Folders and files

Repository files navigation

abap2react ⚑

Build dynamic, reactive full-stack web applications in 100% pure ABAP with Preact & TailwindCSS on the frontend.

Inspired by the pioneering concept of abap2UI5, abap2react takes the paradigm of server-driven ABAP web development to the modern JavaScript ecosystem β€” combining ultra-lightweight Preact Virtual DOM, TailwindCSS design tokens, and a bidirectional state engine.

Supports both SAP BTP / ABAP Cloud (RAP / Steampunk) and SAP On-Premise (SICF).


πŸ’‘ Inspiration & Comparison: abap2react vs abap2UI5

abap2UI5 proved that enterprise ABAP developers can build full-stack web applications without writing frontend JavaScript. abap2react builds upon this vision by replacing the heavy OpenUI5 control library with a lightweight React / Preact Virtual DOM engine and modern TailwindCSS styling.

Feature / Metric πŸš€ abap2react πŸ›οΈ abap2UI5
Frontend Framework Preact (10.x) + HTM (Virtual DOM) OpenUI5 / SAPUI5 (Control Tree)
Asset Bundle Size ~50 KB (ultra-lightweight single file) ~15 - 30 MB (UI5 core libraries)
First Contentful Paint (FCP) < 100 ms (Instant load) ~1.5s - 3.5s (Library bootstrapping)
Styling & Theming TailwindCSS utility classes + Dynamic CSS tokens SAP Fiori Theme Designer / UI5 themes
View Definition Clean HTML5 tags + <if>, <for>, <fragment> UI5 XML View controls (sap.m.*, sap.ui.table.*)
Client Actions Pipeline Unified Action Dispatcher (Toast, Modal, Clipboard, Download, etc.) Custom UI5 event handlers & controller extensions
Security & CSP 100% Zero-Eval & CSP-Safe expression engine Standard SAPUI5 runtime
Integrated DevTools Built-in DevTools Drawer (Ctrl+F12) with state, XML, roundtrip log & nav stack UI5 Diagnostics tool (Ctrl+Alt+Shift+S)
Offline Mode 100% self-contained single-file HTML (Zero CDN runtime) Requires full UI5 library deployment

🌟 Key Architecture & Features

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    ABAP Backend (Server)                    β”‚
β”‚                                                             β”‚
β”‚  z2react_if_app  ──►  z2react_cl_view_builder  ──► XML View β”‚
β”‚         β–²                                             β”‚     β”‚
β”‚         β”‚ JSON State & Events                         β–Ό     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”˜
          β”‚  HTTP POST (SICF / ABAP Cloud ICF)          β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”
β”‚         β–Ό                                             β–Ό     β”‚
β”‚  State Engine ◄──► Preact Virtual DOM ◄─── XML Parser Engineβ”‚
β”‚                                                             β”‚
β”‚              Frontend Client (Browser Runtime)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. Pure ABAP Development:
    • 100% of your business logic, state schemas, and view templates are written in ABAP classes implementing z2react_if_app.
  2. Two-Way State Binding:
    • client->bind( ms_state-field ) synchronizes React form controls (inputs, checkboxes, radios, selects, textareas, sliders) and ABAP backend state in real time.
  3. Cached View & Lightweight State Roundtrips:
    • View templates are sent only on initialization (client->check_on_init( )). Subsequent user interactions transmit only lightweight JSON state payloads.
  4. Declarative Control Flow:
    • <if condition="{IS_ACTIVE}"> ... <else> ... </if>
    • <for each="{T_ITEMS}"> ... </for>
    • <fragment> ... </fragment>
  5. Bidirectional Multi-Screen Navigation:
    • Push screen: client->nav_call( NEW zcl_sub_app( ) ).
    • Pop screen with return data: client->nav_leave( ms_result ).
    • Capture return: IF client->check_on_navigated( ). client->get_app_prev_arg( IMPORTING result = ls_ret ). ENDIF.
  6. Comprehensive Client Action Pipeline:
    • Toast Notifications: client->toast_display( text = '...' type = z2react_if_client=>cs_toast_type-success )
    • Interactive Message Boxes: client->message_box_display( title = '...' confirm_event = 'CONFIRM_DELETE' )
    • Dynamic XML Popups: client->popup_show( lv_popup_xml ) & client->popup_close( )
    • Clipboard Access: client->clipboard_write( '...' ) & client->clipboard_read( 'ON_PASTE' ) β€” includes an automatic fallback (copy event) for non-secure HTTP contexts
    • File Operations: Trigger downloads via client->file_download( ... ) and uploads via <input type="file" value="{FILE}" />
    • Focus & Smooth Scroll: client->set_focus( 'inp-id' ) & client->scroll_into_view( 'section-id' )
    • Document Head: client->set_title( '...' ) & client->set_favicon( '...' )
    • Global Keyboard Shortcuts: client->keyboard_shortcut( key = 's' ctrl = abap_true event = 'SAVE' )
    • Unsaved Changes Guard: client->set_dirty_state( abap_true )
    • Theme Tokens: Dynamic CSS variables via client->set_theme_token( key = '--primary' val = '#6366f1' )
  7. Integrated DevTools:
    • Press Ctrl + F12 (or Ctrl + Shift + D) to inspect live State JSON, XML View, Navigation Stack, and Roundtrip telemetry.

πŸš€ Quick Start

1. Installation via abapGit

Install the repository into your SAP system using abapGit:

  • Repository URL: https://github.com/furkancosgun/abap2react.git
  • Package: $ABAP2REACT (or your chosen development package)

2. Local Development & Testing

# Clone the repository
git clone https://github.com/furkancosgun/abap2react.git
cd abap2react

# Install dependencies
npm install

# Run local development server (http://localhost:3000)
npm run dev

# Run full test suite (Linter + Unit + Playwright E2E)
npm run test:all

πŸ“– Code Examples

1. Basic Reactive Counter & Form

CLASS zcl_demo_counter DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES z2react_if_app.

    TYPES:
      BEGIN OF ty_s_state,
        user_name TYPE string,
        counter   TYPE i,
      END OF ty_s_state.

    DATA ms_state TYPE ty_s_state.
ENDCLASS.

CLASS zcl_demo_counter IMPLEMENTATION.
  METHOD z2react_if_app~main.
    " 1. Initial Render
    IF client->check_on_init( ).
      ms_state-user_name = 'Developer'.
      ms_state-counter   = 0.

      DATA(lo_view) = z2react_cl_view_builder=>factory( 'div' )->a( n = 'class' v = 'max-w-md mx-auto my-12 p-8 bg-slate-900 rounded-3xl border border-slate-800 text-white space-y-4' ).
      lo_view->ele( 'h1' )->a( n = 'class' v = 'text-2xl font-bold text-indigo-400' )->text( 'abap2react Counter' ).
      
      lo_view->ele( 'input'
        )->a( n = 'type'  v = 'text'
        )->a( n = 'value' v = client->bind( ms_state-user_name )
        )->a( n = 'class' v = 'w-full px-4 py-2 bg-slate-950 border border-slate-700 rounded-xl text-white' ).

      lo_view->ele( 'div' )->a( n = 'class' v = 'text-4xl font-mono text-cyan-400 py-2' )->text( client->bind( ms_state-counter ) ).

      lo_view->ele( 'button'
        )->a( n = 'onClick' v = client->event( 'INCREMENT' )
        )->a( n = 'class'   v = 'w-full py-3 bg-indigo-600 hover:bg-indigo-500 rounded-xl font-bold transition shadow-lg shadow-indigo-600/30'
        )->text( '+1 Increment' ).

      client->view_display( lo_view->stringify( ) ).
      RETURN.
    ENDIF.

    " 2. Event Handling
    CASE client->get_event( ).
      WHEN 'INCREMENT'.
        ms_state-counter += 1.
        client->toast_display( text = |Counter updated: { ms_state-counter }| type = z2react_if_client=>cs_toast_type-success ).
    ENDCASE.
  ENDMETHOD.
ENDCLASS.

2. Multi-Screen Navigation (Screen A ──► Screen B)

Screen A: Caller

CLASS zcl_demo_screen_a DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES z2react_if_app.
    DATA mv_selected_item TYPE string.
ENDCLASS.

CLASS zcl_demo_screen_a IMPLEMENTATION.
  METHOD z2react_if_app~main.
    " Catch return data when Screen B finishes
    IF client->check_on_navigated( ).
      client->get_app_prev_arg( IMPORTING result = mv_selected_item ).
      client->toast_display( text = |Returned from Screen B: { mv_selected_item }| ).
    ENDIF.

    IF client->check_on_init( ).
      DATA(lo_view) = z2react_cl_view_builder=>factory( 'div' )->a( n = 'class' v = 'p-8 max-w-lg mx-auto text-white' ).
      lo_view->ele( 'h2' )->text( 'Screen A' ).
      lo_view->ele( 'button'
        )->a( n = 'onClick' v = client->event( 'OPEN_SCREEN_B' )
        )->a( n = 'class'   v = 'px-4 py-2 bg-indigo-600 rounded-xl'
        )->text( 'Go to Screen B' ).
      client->view_display( lo_view->stringify( ) ).
      RETURN.
    ENDIF.

    IF client->check_on_event( 'OPEN_SCREEN_B' ).
      client->nav_call( NEW zcl_demo_screen_b( ) ).
    ENDIF.
  ENDMETHOD.
ENDCLASS.

Screen B: Sub-Screen

CLASS zcl_demo_screen_b DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES z2react_if_app.
ENDCLASS.

CLASS zcl_demo_screen_b IMPLEMENTATION.
  METHOD z2react_if_app~main.
    IF client->check_on_init( ).
      DATA(lo_view) = z2react_cl_view_builder=>factory( 'div' )->a( n = 'class' v = 'p-8 max-w-lg mx-auto text-white space-y-4' ).
      lo_view->ele( 'h2' )->text( 'Screen B (Sub-screen)' ).
      lo_view->ele( 'button'
        )->a( n = 'onClick' v = client->event( 'SELECT_AND_CLOSE' )
        )->a( n = 'class'   v = 'px-4 py-2 bg-emerald-600 rounded-xl'
        )->text( 'Confirm & Return Item #42' ).
      client->view_display( lo_view->stringify( ) ).
      RETURN.
    ENDIF.

    IF client->check_on_event( 'SELECT_AND_CLOSE' ).
      client->nav_leave( 'Item #42' ).
    ENDIF.
  ENDMETHOD.
ENDCLASS.

🌐 HTTP ICF Setup

SAP BTP / ABAP Cloud (RAP)

CLASS zcl_http_service DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_web_http_service_extension.
ENDCLASS.

CLASS zcl_http_service IMPLEMENTATION.
  METHOD if_web_http_service_extension~handle_request.
    z2react_cl_http_handler=>factory_cloud( request  = request
                                            response = response ).
  ENDMETHOD.
ENDCLASS.

SAP On-Premise (Transaction SICF)

CLASS zcl_sicf_handler DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_http_extension.
ENDCLASS.

CLASS zcl_sicf_handler IMPLEMENTATION.
  METHOD if_http_extension~handle_request.
    z2react_cl_http_handler=>factory_onprem( server ).
  ENDMETHOD.
ENDCLASS.

πŸ› οΈ CLI & NPM Scripts

Command Description
npm run dev Starts local development server on http://localhost:3000
npm run build Bundles modular ESM frontend with Vite & transpiles ABAP classes
npm run bundle:online Bundles online SingleFile HTML shell into ABAP asset class
npm run bundle:offline Bundles 100% offline self-contained HTML shell (Zero CDN JS/CSS) into ABAP
npm test Runs abaplint rules and unit tests with @abaplint/runtime
npm run test:e2e Executes all 37 Playwright E2E integration tests
npm run test:all Runs full suite: lint + lint:e2e + unit + test:e2e
npm run lint:fix Automatically fixes abaplint formatting issues

πŸ“„ License

Distributed under the MIT License. See LICENSE for more information.


❀️ Acknowledgements

  • abap2UI5 for pioneering the pure ABAP web app architecture.
  • open-abap and abaplint for enabling server-side ABAP transpilation and local testing.
  • Preact and TailwindCSS for powering fast, modern web interfaces.

About

Build dynamic, reactive full-stack web applications in 100% pure ABAP with Preact & TailwindCSS on the frontend.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages