4

abap2UI5 – (2/3) Output of Lists & Tables – add toolbars and make editable

 1 year ago
source link: https://blogs.sap.com/2023/02/22/abap2ui5-output-of-lists-and-tables-toolbar-and-editable-2-3/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
February 22, 2023 11 minute read

abap2UI5 – (2/3) Output of Lists & Tables – add toolbars and make editable

0 17 1,843

This is the second blog post of a blog series which introduces the abap2UI5 Project. It focuses on the output of lists and tables. All project information can be found on GitHub and Twitter:

Blog Series

(1/3) ABAP2UI5 – Development of UI5 Apps in pure ABAP This blog post focuses on how we can use ABAP2UI5 to develop applications in general
(2/3) ABAP2UI5 – Lists, Tables, Toolbar and editable (this blog post) Examples to display lists and tables with an ABAP2UI5 application are explained here.
(3/3) ABAP2UI5 – Demo apps (coming soon) Some full working demo apps are introduced in this blog post.

If you are interested in the technical background, take a look at this first blog post: ABAP2UI5 – Development of UI5 Selection Screens in pure ABAP

Introduction

Let’s take a look to the classic sap-gui way to display tables in ABAP first:

TYPES: BEGIN OF t_flight,
         carrid TYPE s_carr_id,
         connid TYPE s_conn_id,
         fldate TYPE s_date,
         price TYPE s_price,
       END OF t_flight.

DATA: it_flight TYPE STANDARD TABLE OF t_flight.

SELECT carrid connid fldate price FROM sflight INTO TABLE it_flight.

DATA: gr_flight TYPE REF TO cl_gui_alv_grid.
CREATE OBJECT gr_flight
  EXPORTING
    i_parent = cl_gui_container=>screen0.

gr_flight->set_table_for_first_display(
  EXPORTING
    i_structure_name = 'T_FLIGHT'
  CHANGING
    it_outtab = it_flight ).

Around of 25 lines of pure ABAP are needed and you get a UI with a table output. That is very efficient! And with only a few lines more you can also add buttons, inputs and interactions.

When we now try to bring this example to a non-sap-gui environment we need to start with Fiori Elements/RAP or develop an UI5 freestyle application. The first way needs a lot of DDL and CDS artifacts, the second way needs javascript knowledge and the organisation of BAS development environemnts or deployment processes.

Both ways do not fullfill the one page source code idea. The code of abap2UI5 for this example looks like this:

CLASS z2ui5_cl_app_demo_03 DEFINITION PUBLIC.

  PUBLIC SECTION.
    INTERFACES z2ui5_if_app.

TYPES: BEGIN OF t_flight,
         carrid TYPE s_carr_id,
         connid TYPE s_conn_id,
         fldate TYPE s_date,
         price TYPE s_price,
       END OF t_flight.
   DATA t_flight TYPE STANDARD TABLE OF t_flight.

ENDCLASS.

CLASS z2ui5_cl_app_demo_03 IMPLEMENTATION.

  METHOD z2ui5_if_app~controller.

    CASE client->get( )-lifecycle_method.

      WHEN client->cs-lifecycle_method-on_init.
        SELECT carrid connid fldate price FROM sflight INTO TABLE t_flight.

      WHEN client->cs-lifecycle_method-on_rendering.

        data(view) = client->factory_view( ).
        view->page( )->list( items = view->_bind_one_way( t_tab )
                  )->standard_list_item(
                        title       = '{CARRID}'
                        description = '{CONNID}'
                        info        = '{FLDATE}'  ).

    ENDCASE.
  ENDMETHOD.
ENDCLASS.

Abap2UI5 needs a few more lines, but the code is also in ABAP OO for that 😉

Toolbar

The abap2UI5 output of a table with toolbar in a scroll container looks like this:

Bildschirm%C2%ADfoto-2023-02-19-um-19.54.31.png

So far the view definition is the same as in the first blog post, when we defined a selection screen. We just use the table control instead. Similar to a fieldcat the column definition is set.:

"set table and container
DATA(tab) = page->scroll_container( '70%' )->table( view->_bind_one_way( t_tab ) ).

"set toolbar
tab->header_toolbar( )->overflow_toolbar(
        )->title( 'title of the table'
             )->toolbar_spacer(
             )->button( text = 'Sort' press = view->_event( 'BUTTON_SORT' )
             )->button( text = 'Post' press = view->_event( 'BUTTON_POST' ) ).

"set header
tab->columns(
            )->column( )->text( 'Title' )->get_parent(
            )->column( )->text( 'Color' )->get_parent(
            )->column( )->text( 'Info' )->get_parent(
            )->column( )->text( 'Description' )->get_parent(
            )->column( )->text( 'Checkbox' ).

"set content
tab->items( )->column_list_item( )->cells(
           )->text( '{TITLE}'
           )->text( '{VALUE}'
           )->text( '{INFO}'
           )->text( '{DESCR}'
           )->checkbox( '{CHECKBOX}' ).

It would be no problem to do some RTTS and to encapsulate, that everything is set automatically and in a generic way like in CL_SALV_TABLE, but like in the first blog post explained abap2Ui5 just wants to give the basic functionality.

Most important is the data binding:

"set table and container
DATA(tab) = page->scroll_container( '70%' 
                    )->table( items = view->_bind_one_way( t_tab ) ).

In contrast for example to the text control we can not write the value of the attribute directly into the XML because the table is a deep data model. Therefore it must be written into the View Model of the UI5 View. But Abap2UI5 takes automatically care of this, you just need to use the method bind_one_way and put your table in it. The data is then transformed to a JSON Table and send to the frontend as a part of the UI5 View Model.

Next let’s see how we can make the table editable.

Selection Modes

(coming soon)

Editable

Demo:

Demo%20Editable%20Table

Demo Editable Table

The code looks very similar to the first example:

CLASS z2ui5_cl_app_demo_11 DEFINITION PUBLIC.

  PUBLIC SECTION.
    INTERFACES z2ui5_if_app.

    TYPES:
      BEGIN OF ty_row,
        title    TYPE string,
        value    TYPE string,
        descr    TYPE string,
        icon     TYPE string,
        info     TYPE string,
        checkbox TYPE abap_bool,
      END OF ty_row.

    DATA t_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
    DATA check_editable_active TYPE abap_bool.

ENDCLASS.

CLASS Z2UI5_CL_APP_DEMO_11 IMPLEMENTATION.

  METHOD z2ui5_if_app~controller.

    CASE client->get( )-lifecycle_method.

      WHEN client->cs-lifecycle_method-on_init.

        check_editable_active = abap_false.

        t_tab = REDUCE #( INIT ret = VALUE #( ) FOR n = 1 WHILE n < 10 NEXT ret =
            VALUE #( BASE ret ( title = 'Hans'  value = 'red' info = 'completed'  descr = 'this is a description' checkbox = abap_true )  ) ).

      WHEN client->cs-lifecycle_method-on_event.

        CASE client->get( )-event.

          WHEN 'BUTTON_EDIT'.
            check_editable_active = xsdbool( check_editable_active = abap_false ).
        ENDCASE.

      WHEN client->cs-lifecycle_method-on_rendering.

        DATA(view) = client->factory_view( ).
        DATA(page) = view->page( title = 'Example - ZZ2UI5_CL_APP_DEMO_11' nav_button_tap = view->_event_display_id( client->get( )-id_prev_app ) ).

        DATA(tab) = page->table( view->_bind( t_tab ) ).

        "set toolbar
        tab->header_toolbar( )->overflow_toolbar(
            )->title( 'title of the table'
             )->toolbar_spacer(
             )->button(
                    text = SWITCH #( check_editable_active WHEN abap_true THEN 'display' ELSE 'edit' )
                    press = view->_event( 'BUTTON_EDIT' ) ).

        "set header
        tab->columns(
            )->column( )->text( 'Title' )->get_parent(
            )->column( )->text( 'Color' )->get_parent(
            )->column( )->text( 'Info' )->get_parent(
            )->column( )->text( 'Description' )->get_parent(
            )->column( )->text( 'Checkbox' ).

        "set columns
        IF check_editable_active = abap_true.

          tab->items( )->column_list_item( )->cells(
              )->input( '{TITLE}'
              )->input( '{VALUE}'
              )->input( '{INFO}'
              )->input( '{DESCR}'
              )->checkbox( selected = '{CHECKBOX}' enabled = abap_true ).

        ELSE.
          tab->items( )->column_list_item( )->cells(
             )->text( '{TITLE}'
             )->text( '{VALUE}'
             )->text( '{INFO}'
             )->text( '{DESCR}'
             )->checkbox( '{CHECKBOX}' ).
        ENDIF.
    ENDCASE.
  ENDMETHOD.
ENDCLASS.

There is a difference in the column definition, when the editable function is activated we use input controls instead of text controls:

 IF check_editable_active = abap_true.

      tab->items( )->column_list_item( )->cells(
              )->input( '{TITLE}'
              )->input( '{VALUE}'
              )->input( '{INFO}'
              )->input( '{DESCR}'
              )->checkbox( selected = '{CHECKBOX}' enabled = abap_true ).

 ELSE.
      tab->items( )->column_list_item( )->cells(
             )->text( '{TITLE}'
             )->text( '{VALUE}'
             )->text( '{INFO}'
             )->text( '{DESCR}'
             )->checkbox( '{CHECKBOX}' ).
ENDIF.

Furthermore we need to make sure that abap2UI5 sends back the updated values to the server. Therefore we have to use a different data binding compared to the first example:

DATA(tab) = page->table( items = view->_bind( t_tab ) ).

With the method _bind( ) abap2UI5 creates a two way binding with this table. That means first the data is transformed to a JSON Model and send to the frontend. Second with every request it is also send back to the backend. So make sure your table t_tab is a public attribute that abap2UI5 can assign it from outside and update the values.

Runtime

The request processing for two-way-binding with tables has higher costs than one-way-binding, because after every request there is a JSON to ABAP mapping processed to update the edited table. Therefore only use two-way-binding when it is really needed and maybe don’t make ten thousands of entries editable at once. But who knows a user who edits 10.000 entries at the same time? And there is no UI5 control which renders so many entries anyway.

Selection-Screens

Example%20View
UI5-View vs. abap2UI5-View
<Page title="Example - ZZ2UI5_CL_APP_DEMO_02" showNavButton="true" navButtonTap="onEvent">
	<l:Grid defaultSpan="L6 M12 S12" class="sapUiSmallMarginTop">
		<l:content>
			<f:SimpleForm title="Input">
				<f:content>
					<Label text="Input with value help" />
					<Input placeholder="fill in your favorite colour" showClearIcon="false" editable="true" value="{/oUpdate/SCREEN-COLOUR}" suggestionItems="{/MT_SUGGESTION}" showSuggestion="true">
						<suggestionItems>
							<core:ListItem text="{VALUE}" additionalText="{DESCR}" />
						</suggestionItems>
					</Input>
				</f:content>
			</f:SimpleForm>
			<f:SimpleForm title="Time Inputs" editable="true">
				<f:content>
					<Label text="Date" />
					<DatePicker value="{/oUpdate/SCREEN-DATE}" />
					<Label text="Date and Time" />
					<DateTimePicker value="{/oUpdate/SCREEN-DATE_TIME}" />
					<Label text="Time Begin/End" />
					<TimePicker value="{/oUpdate/SCREEN-TIME_START}" />
					<TimePicker value="{/oUpdate/SCREEN-TIME_END}" />
				</f:content>
			</f:SimpleForm>
		</l:content>
	</l:Grid>
	<l:Grid defaultSpan="L12 M12 S12" class="sapUiSmallMarginTop">
		<l:content>
			<f:SimpleForm title="Input with select options" editable="true">
				<f:content>
					<Label text="Checkbox" />
					<CheckBox text="this is a checkbox" selected="{/oUpdate/SCREEN-CHECK_IS_ACTIVE}" enabled="true" />
					<Label text="Combobox" />
					<ComboBox showClearIcon="false" selectedKey="{/oUpdate/SCREEN-COMBO_KEY}" items="{/1}">
						<core:Item key="{KEY}" text="{TEXT}" />
					</ComboBox>
				</f:content>
				<Label text="Segmented Button" />
				<SegmentedButton selectedKey="{/oUpdate/SCREEN-SEGMENT_KEY}">
					<items>
						<SegmentedButtonItem icon="sap-icon://accept" key="BLUE" text="blue" />
						<SegmentedButtonItem icon="sap-icon://add-favorite" key="GREEN" text="green" />
						<SegmentedButtonItem icon="sap-icon://attachment" key="BLACK" text="black" />
					</items>
				</SegmentedButton>
				<Label text="Switch disabled" />
				<Switch type="Default" enabled="false" state="/2" customTextOff="B" customTextOn="A" />
				<Label text="Switch accept/reject" />
				<Switch type="AcceptReject" enabled="true" state="/oUpdate/SCREEN-CHECK_SWITCH_01" customTextOff="off" customTextOn="on" />
				<Label text="Switch normal" />
				<Switch type="Default" enabled="true" state="/oUpdate/SCREEN-CHECK_SWITCH_02" customTextOff="NO" customTextOn="YES" />
			</f:SimpleForm>
		</l:content>
	</l:Grid>
	<footer>
		<OverflowToolbar>
			<Link text="Go to Source Code" target="_blank" href="" enabled="true" />
			<ToolbarSpacer />
			<Button press="onEvent" text="Clear" enabled="true" icon="sap-icon://delete" type="Reject" />
			<Button press="onEvent" text="Send to Server" enabled="true" type="Success" />
		</OverflowToolbar>
	</footer>
</Page>
DATA(page) = view->page( title = 'Example - ZZ2UI5_CL_APP_DEMO_02' nav_button_tap = view->_event_display_id( client->get( )-id_prev_app ) ).

DATA(grid) = page->grid( 'L6 M12 S12' )->content( 'l' ).

grid->simple_form('Input' )->content( 'f'
        )->label( 'Input with value help'
        )->input(
            value       = view->_bind( screen-colour )
            placeholder = 'fill in your favorite colour'
            suggestion_items = view->_bind_one_way( mt_suggestion ) )->get(
            )->suggestion_items( )->get(
                )->list_item( text = '{VALUE}' additional_text = '{DESCR}' ).

grid->simple_form('Time Inputs' )->content( 'f'
        )->label( 'Date'
        )->date_picker( view->_bind( screen-date )

        )->label( 'Date and Time'
        )->date_time_picker( view->_bind( screen-date_time )

        )->label( 'Time Begin/End'
        )->time_picker( view->_bind( screen-time_start )
        )->time_picker( view->_bind( screen-time_end ) ).

page->grid( default_span  = 'L12 M12 S12' )->content( 'l'
       )->simple_form('Input with select options' )->content( 'f'

    )->label( 'Checkbox'
    )->checkbox(
         selected = view->_bind( screen-check_is_active )
         text     = 'this is a checkbox'
         enabled  = abap_true

    )->label( 'Combobox'
    )->combobox(
         selectedkey = view->_bind( screen-combo_key )
         items      = view->_bind_one_way( VALUE ty_t_combo(
             ( key = 'BLUE'  text = 'green' )
             ( key = 'GREEN' text = 'blue'  )
             ( key = 'BLACK' text = 'red'   )
             ( key = 'GRAY'  text = 'gray'  ) )
         ) )->get( )->item( key = '{KEY}' text = '{TEXT}'
        )->get_parent( )->get_parent(

    )->label( 'Segmented Button'
    )->segmented_button( view->_bind( screen-segment_key ) )->get(
        )->items( )->get(
             )->segmented_button_item( key = 'BLUE'  icon = 'sap-icon://accept'       text = 'blue'
             )->segmented_button_item( key = 'GREEN' icon = 'sap-icon://add-favorite' text = 'green'
             )->segmented_button_item( key = 'BLACK' icon = 'sap-icon://attachment'   text = 'black'
       )->get_parent( )->get_parent(

    )->label( 'Switch disabled'
    )->switch( enabled = abap_false    customtexton = 'A' customtextoff = 'B'
    )->label( 'Switch accept/reject'
    )->switch( state = screen-check_switch_01 customtexton = 'on'  customtextoff = 'off' type = 'AcceptReject'
    )->label( 'Switch normal'
    )->switch( state = screen-check_switch_02 customtexton = 'YES' customtextoff = 'NO' ).

page->footer( )->overflow_toolbar(
         )->link(
             text = 'Go to Source Code'
             href = client->get( )-s_request-url_source_code
         )->toolbar_spacer(
         )->button(
             text  = 'Clear'
             press = view->_event( 'BUTTON_CLEAR' )
             type  = 'Reject'
             icon  = 'sap-icon://delete'
         )->button(
             text  = 'Send to Server'
             press = view->_event( 'BUTTON_SEND' )
             type  = 'Success' ).

In this example you can see that you need 70 lines of code for a view. Maybe that seems to be a lot for a single view and the generating process is very technical. But again abap2UI5 just wants to provide the basic layer and functionality to create UI5 applications so that the system footprint of abap2UI5 stays very small. Apart from this every user can build useful wrappers around the view rendering.

Summary

Abap2UI5 provides a quick and easy way to display tables and lists. Also the use of toolbars or including an editable function is no problem. These two example are very basic, you can add a lot more controls to the view to make the table output more beautiful or extend the whole functionality of the app.

A lot more controls to display table data can be added to abap2UI5 in the future, for example the sap.ui.table or the timeline control. In addition the functionality of selected rows and sending this events back to the server can be part of it in the future.

Feel free to install this project and try out the examples and demos. For news and improvements follow this project on Twitter or take a look to the GitHub repository.

Your comments, questions and wishes are welcome, create an issue or leave a comment.

Thanks for reading!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK