• Inicio
  • Novedades
  • Academia SAP
  • FAQ
  • Blog
  • Contacto
S4PCADEMY_Logo
Twitter Linkedin Instagram
S4PCADEMY_Logo
Twitter Linkedin Instagram
ABAP2UI5  ·  Technical Articles

ABAP2UI5 – Salida de Listas y Tablas, Barra de Herramientas y Editable (2/3)

By s4pcademy 


Esta serie de blogs presenta la Proyecto ABAP2UI5. Es un proyecto de código abierto que lo ayuda a desarrollar aplicaciones UI5 independientes en ABAP puro. Toda la información que necesita para instalar el proyecto se puede encontrar en GitHub y para próximas novedades y mejoras puedes seguir el proyecto en Gorjeo.

Esta es la segunda publicación de blog que se enfoca en la salida de modelos de datos profundos como tablas.

Serie de blogs:

Si está interesado en los antecedentes técnicos, eche un vistazo a esta primera publicación de blog: ABAP2UI5 – Desarrollo de Pantallas de Selección UI5 en ABAP puro

Introducción (los buenos viejos tiempos)

ChatGPT me dio este fragmento cuando pedí una forma de mostrar tablas en ABAP:

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 ).

Solo alrededor de 25 líneas de ABAP puro y obtienes una interfaz de usuario con una salida de tabla. Eso es muy eficiente, pero cuando luego pedí una forma que no fuera sap-gui o lista para la nube, por supuesto, chatGPT no conocía otra forma que no fuera Fiori Elements y terminó con puro ABAP. ABAP2UI5 intenta llenar este vacío y proporciona una forma no sap-gui y preparada para la nube de generar interfaces de usuario. El código ABAP2UI5 para este ejemplo se ve así:

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.

De acuerdo, ABAP2UI5 necesita algunas líneas más, pero el código también está en ABAP OO para eso 😉

Mostrar tabla con barra de herramientas

La salida ABAP2UI5 de una tabla con barra de herramientas en un contenedor de desplazamiento se ve así:

CLASS z2ui5_cl_app_demo_06 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.

ENDCLASS.

CLASS Z2UI5_CL_APP_DEMO_06 IMPLEMENTATION.


  METHOD z2ui5_if_app~controller.

    CASE client->get( )-lifecycle_method.

      WHEN client->cs-lifecycle_method-on_init.

        t_tab = REDUCE #( INIT ret = VALUE #( ) FOR n = 1 WHILE n < 101 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_SORT'.
            SORT t_tab BY value.

          WHEN 'BUTTON_POST'.
            client->display_message_box( 'button post was pressed' ).
        ENDCASE.


      WHEN client->cs-lifecycle_method-on_rendering.

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

        "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}' ).

    ENDCASE.

  ENDMETHOD.
ENDCLASS.

Hasta ahora, la definición de la vista es la misma que en la primera publicación del blog, cuando definimos una pantalla de selección. Simplemente usamos el control de tabla en su lugar.

No hay fieldcat y las columnas se definen manualmente:

"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}' ).

No sería problema hacer algo de RTTS y encapsular, que la definición de la columna se establece automáticamente y de forma genérica como en CL_SALV_TABLE, pero como se explicó en la primera publicación del blog, ABAP2Ui5 solo quiere dar la funcionalidad básica y el resto está listo. al usuario

Lo más importante es el enlace de datos:

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

A diferencia, por ejemplo, del control de texto, no podemos escribir el valor del atributo directamente en el XML porque la tabla es un modelo de datos profundo. Por lo tanto, debe escribirse en el modelo de vista de la vista UI5. Pero no se preocupe por eso, ABAP2UI5 se encarga de esto, solo necesita usar el método bind_one_way y colocar su tabla en él. ABAP2UI5 luego transforma estos datos en una tabla JSON, los envía a la interfaz y los vincula con el modelo de vista a la vista XML de UI5.

A continuación, veamos cómo podemos hacer que la tabla sea editable.

Editable

CL_GUI_ALV_GRID tiene la funcionalidad (no oficial) para hacerlo editable, CL_SALV_TABLE aún está esperando, ABAP2UI5 se ve así:

Demostración%20Editable%20Tabla

Tabla editable de demostración

El código se parece mucho al primer ejemplo:

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.

Hay una diferencia en la definición de la columna, cuando la función editable está activada usamos controles de entrada en lugar de controles de texto:

 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.

Además, debemos asegurarnos de que ABAP2UI5 devuelva los valores actualizados al servidor. Por lo tanto, tenemos que usar un enlace de datos diferente en comparación con el primer ejemplo:

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

Con el método _bind() ABAP2UI5 crea un enlace bidireccional con esta tabla. Eso significa que primero los datos se transforman en un json y se envían a la interfaz y, en segundo lugar, con cada solicitud, también se envían de vuelta al backend. Así que asegúrese de que su tabla t_tab sea un atributo público que ABAP2UI5 pueda asignarle desde afuera y actualice los valores.

tiempo de ejecución

El procesamiento de solicitudes para el enlace bidireccional con tablas tiene costos un poco más altos que el enlace unidireccional porque después de cada solicitud se procesa una asignación de JSON a ABAP para actualizar la tabla editada. Por lo tanto, solo use el enlace bidireccional cuando sea realmente necesario y tal vez no haga que miles de entradas se puedan editar a la vez. Pero, ¿quién conoce a un usuario que edita 10.000 entradas al mismo tiempo? Y no hay ningún control UI5 que genere tantas entradas de todos modos. Cientos o miles de entradas y cada caso de uso más realista no es un problema con este enfoque.

Conclusión

ABAP2UI5 proporciona una forma rápida y sencilla de mostrar tablas y listas. Además, el uso de barras de herramientas o incluir una función editable no es un problema. Estos dos ejemplos son muy básicos, puede agregar muchos más controles a la vista para hacer que la salida de la tabla sea más hermosa o ampliar toda la funcionalidad de la aplicación.

En el futuro, se agregarán muchos más controles para mostrar los datos de la tabla a ABAP2UI5, por ejemplo, sap.ui.table o el control de línea de tiempo. Además, la funcionalidad de las filas seleccionadas y el envío de estos eventos al servidor pueden ser parte de ABAP2Ui5 en el futuro.

¿Qué opinas sobre este enfoque? Siéntase libre de compartir sus comentarios, ideas y deseos.

¡Gracias por leer!






Abap2ui5barraEditableherramientasListassalidatablas

Artículos relacionados


#activating gos  ·  #gos toolbar  ·  #GOS_in_CRM_Billing_Document  ·  #GOS_in_CRM_WebUI  ·  Technical Articles
Mostrar datos de la barra de herramientas de GOS en la pantalla de interfaz de usuario web de facturación de CRM
Personal Insights
Cómo encontrar aplicaciones de importación de documentos de ventas (p. ej., contratos de ventas de importación) mediante la barra de búsqueda
ABAP2UI5  ·  Technical Articles
ABAP2UI5 – Desarrollo de Apps UI5 en puro ABAP (1/3)
ABAP2UI5 – Desarrollo de Apps UI5 en puro ABAP (1/3)
Previo
日本語翻訳版:SAP Human Capital Management para SAP S/4HANA ahora disponible como parte del lanzamiento de SAP S/4HANA 2022
Siguiente

Madrid

Calle Eloy Gonzalo, 27
Madrid, Madrid.
Código Postal 28010

México

Paseo de la Reforma 26
Colonia Juárez,  Cuauhtémoc
Ciudad de México 06600

Costa Rica

Real Cariari
Autopista General Cañas, 
San José, SJ 40104

Perú

Av. Jorge Basadre 349
San Isidro
Lima, LIM 15073

Twitter Linkedin Instagram
Copyright 2022 | All Right Reserved.