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

ABAP2UI5 – Desarrollo de Apps UI5 en puro ABAP (1/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. El predecesor se introdujo en este entrada en el blog. El proyecto ahora tiene algunas mejoras que permiten usar una amplia gama de controles UI5. Por ejemplo, ahora es posible mostrar tablas y listas y definir diferentes diseños con encabezados y pies de página. Con estos, puede crear aplicaciones para muchos casos de uso diferentes.

Idea general

ABAP2UI5 quiere proporcionar una forma «lista para la nube» y «no sap-gui» para crear aplicaciones UI5 en ABAP puro sin usar OData, Javascript, anotaciones o RAP, como en los «viejos tiempos» cuando solo necesitábamos unas pocas líneas. de código ABAP para mostrar tablas y entradas con el marco CL_GUI_ALV_GRID y CL_GUI_CFW.

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

Información del proyecto

Toda la información del proyecto se puede encontrar en el repositorio de GitHub y en twitter:

Manifestación

Para obtener una primera impresión de ABAP2UI5, eche un vistazo a esta demostración: todo se crea en el backend en ABAP puro. No se necesita implementación de aplicaciones ni javascript adicionales:

Una aplicación de ejemplo se ve así:

CLASS z2ui5_cl_app_demo_01 DEFINITION PUBLIC.

  PUBLIC SECTION.

    INTERFACES z2ui5_if_app.

    DATA product TYPE string.
    DATA quantity TYPE string.

ENDCLASS.

CLASS Z2UI5_CL_APP_DEMO_01 IMPLEMENTATION.

  METHOD z2ui5_if_app~controller.

    CASE client->get( )-lifecycle_method.

      WHEN client->cs-lifecycle_method-on_init.
        product="tomato".
        quantity = '500'.

      WHEN client->cs-lifecycle_method-on_event.

        CASE client->get( )-event.

          WHEN 'BUTTON_POST'.
            client->display_message_toast( |{ product } { quantity } ST - GR successful| ).

        ENDCASE.

      WHEN client->cs-lifecycle_method-on_rendering.

        DATA(view) = client->factory_view( ).

        view->page( title="Page title"
           )->simple_form('Form Title'
             )->content( 'f'
                )->title( 'Input'
                )->label( 'quantity'
                )->input( view->_bind( quantity )
                )->label( 'product'
                )->input( value = product editable = abap_False
                )->button( text="post" press = view->_event( 'BUTTON_POST' ) ).

    ENDCASE.
  ENDMETHOD.
ENDCLASS.

Los otros ejemplos de código se pueden encontrar aquí:

Pantalla de selección / Lista / Mesa

Como puedes ver, lo único que tienes que hacer para desarrollar una aplicación UI5 con ABAP2UI5 es crear una nueva clase implementando la siguiente interfaz:

INTERFACE z2ui5_if_app
  PUBLIC .

  INTERFACES if_serializable_object.

  METHODS controller
    IMPORTING
      client TYPE REF TO z2ui5_if_client.

ENDINTERFACE.

Repasemos el proceso de desarrollo paso a paso comenzando con el controlador:

Controlador

La interfaz Z2UI5_IF_APP proporciona el método «controlador», que le brinda el control de la aplicación UI5 de interfaz similar a un controlador Javascript de una aplicación de estilo libre UI5. Por lo tanto, se ven muy similares:

Controlador UI5 frente a controlador ABAP2UI5
sap.ui.controller("sap.ui.myApp.controller.one", {

	onInit: function() {

	},

	onBeforeRendering: function() {
		 
	},

	onEvent: function() {
	//button event handling here
	},

	onAfterRendering: function() {
		
	},

	onExit: function() {

	}
	
});
METHOD z2ui5_if_app~controller.

    CASE client->get( )-lifecycle_method.

      WHEN client->cs-lifecycle_method-on_init.
       "set initial values....

      WHEN client->cs-lifecycle_method-on_event.
        "event handling....

      WHEN client->cs-lifecycle_method-on_rendering.
        DATA(view) = client->factory_view( ).
        "rendering here....

    ENDCASE.

ENDMETHOD.

El controlador ABAP2UI5 tiene tres eventos de ciclo de vida. La ruta on_init se llama cuando se inicia una aplicación, la ruta on_rendering se llama después de cada solicitud del servidor cuando se representa la vista y la ruta on_event cuando se genera un evento UI5.

Por supuesto, cuando todo se maneja en un solo método, esta no es la idea de un código limpio, pero ABAP2UI5 no quiere establecer ningún requisito sobre cómo se estructuran las aplicaciones. Entonces, solo existe este método como una capa básica y luego cada usuario puede implementar diferentes métodos además de esto por sí mismos. Tal vez uno para init, otro para user_commands, etc.

Vista

ABAP2UI5 brinda la posibilidad de desarrollar vistas de UI5 ​​similares a una aplicación de estilo libre de UI5. La única diferencia es que las vistas no están definidas en XML, sino que se crean con una clase generadora de vistas ABAP2UI5. Con esto, el usuario tiene total libertad para estructurar la vista y también la flexibilidad de usar muchos controles UI5 diferentes. Un ejemplo simple (comparado con una vista UI5 normal) se ve así:

Ejemplo 1

UI5-Vista frente a ABAP2UI5-Vista
<Page title="Page title" showNavButton="true" navButtonTap="onEvent" >
	<f:SimpleForm title="Form Title">
		<f:content>
			<Title text="Input" />
			<Label text="quantity"/>
			<Input editable="true" value="{/oUpdate/QUANTITY}"/>
			<Label text="product" />
			<Input value="tomato" />
			<Button press="onEvent" text="post" enabled="true"/>
		</f:content>
	</f:SimpleForm>
</Page>
view->page( title="Page title" nav_button_tap = view->_event_display_id( client->get( )-id_prev_app )
        )->simple_form('Form Title'
          )->content( 'f'
             )->title( 'Input'
             )->label( 'quantity'
             )->input( view->_bind( quantity )
             )->label( 'product'
             )->input( value = product editable = abap_False
             )->button( text="post" press = view->_event( 'BUTTON_POST' ) ).

Y un ejemplo más detallado se ve así:

Ejemplo 2

UI5-Vista frente a ABAP2UI5-Vista
<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" ).

En el segundo ejemplo, puede ver que necesita 70 líneas de código para una vista. Tal vez eso parezca mucho para una sola vista y el proceso de generación es muy técnico. Pero, de nuevo, ABAP2UI5 solo quiere proporcionar la capa básica y la funcionalidad para crear aplicaciones UI5 para que el espacio ocupado por el sistema de ABAP2UI5 sea muy pequeño. Aparte de esto, cada usuario puede crear contenedores útiles alrededor de la representación de la vista.

Biblioteca ABAP2UI5

En este momento, los siguientes controles de UI5 ​​están disponibles y se agregarán más en el futuro:

¿Qué controles UI5 funcionan con ABAP2UI5?

Solo funcionan los controles que no tienen su «propia lógica de javascript». Eso significa que, por ejemplo, podemos usar el control de entrada, porque tiene solo unos pocos atributos, que se envían directamente al servidor y no necesitamos ningún javascript adicional para esto. La mayoría de los controles 70-80% funcionan así, por lo que podemos usarlos con ABAP2UI5 listos para usar.

Controles que necesitan una implementación de Javascript adicional como el Administrador de mensajes no son posibles Pero existiría la posibilidad de crear un control personalizado a su alrededor y hacerlo controlable por el servidor y con esto formar parte de ABAP2UI5. Pero la pregunta es si vale la pena el esfuerzo. En el futuro, tiene sentido echar un vistazo a ciertos controles muy populares, pero primero mantengamos ABAP2UI5 simple y omitamos esto.

Eventos

Hay dos métodos de eventos posibles en este momento.

Evento

view->( )->button( 
             text="post" 
             press = view->_event( 'BUTTON_POST' )
 ).
La mayoría de las veces es suficiente enviar un simple comando de usuario al servidor. Para esto puedes usar el método _event()

ID de visualización de evento

 view->page( 
    title.         = 'Page title' 
    nav_button_tap = view->_event_display_id( 
                               client->get( )-id_prev_app ) 
    ).

 
Con este método, ABAP2UI5 vuelve a una respuesta con una identificación determinada. Por ejemplo, esto es muy útil cuando solo desea navegar hacia atrás después de llamar a una nueva aplicación. En la sección REST y borrador, puede ver que cada solicitud genera una nueva identificación y se guarda un borrador del estado real de la aplicación. Eso nos da la posibilidad de saltar también a cada estado anterior con el método _event_display_id()

Si existe la necesidad de más funciones de eventos, es posible ampliar ABAP2UI5 en el futuro.

Modelo (enlace de datos)

Hay tres posibilidades de cómo ABAP2UI5 envía datos a la interfaz:

XML directo

view( )->label( 'product'
      )->input( 
           value    = product 
           editable = abap_false
  ).
         
Simplemente coloque el valor en el atributo, luego ABAP2UI5 escribe el valor directamente en UI5-XML-View y lo envía a la interfaz

Unión unidireccional

view->( )->label( 'product'
        )->input( 
            value    = _bind_one_way( product )
            editable = abap_False
   ).
ABAP2UI5 escribe el valor en el modelo de vista y vincula el modelo de vista a la vista XML. Útil para modelos de datos profundos como tablas, veremos esto en la próxima publicación del blog

Encuadernación bidireccional

view( )->label( 'quantity'
      )->input( view->_bind( quantity ) ).​
Igual que el enlace unidireccional, pero además los valores de interfaz se envían de vuelta al servidor con cada solicitud. Así que asegúrese de que el valor que vincula aquí sean atributos públicos de su aplicación que ABAP2UI5 pueda asignarle y actualizar los valores desde el exterior. Este modo de vinculación es útil para entradas o tablas editables.

Por lo tanto, el usuario tiene que decidir durante la definición de la vista cómo se envían los datos a la interfaz y si se deben devolver o no. Para mantener pequeña la carga útil de la solicitud, es una buena idea usar el enlace bidireccional solo si es necesario y los valores se cambian en la interfaz. También se recomienda no sobrecargar la aplicación con miles de atributos, porque ABAP2Ui5 realiza un bucle después de cada solicitud sobre todos los atributos de la clase y verifica si existen valores que deban actualizarse. Hasta ahora nunca he tenido problemas, pero tenga en cuenta que hay un bucle funcionando en segundo plano.

DESCANSO y Borrador

Todo el marco se basa en REST, por lo tanto, no existe ninguna sesión entre dos solicitudes y es compatible con cualquier caso de uso móvil o dispositivo móvil. También es compatible con entornos “tranquilos” como BTP ABAP Environment o la nueva versión de lenguaje ABAP Cloud.

Además, después de cada solicitud, el estado real de la aplicación se serializa y persiste en la base de datos. Z2UI5_IF_APP incluye la interfaz IF_SERIALIZABLE_OBJECT, por lo tanto, es posible usar atributos de la instancia de la aplicación entre dos solicitudes y se siente como trabajar con una aplicación con estado como en un entorno de pantalla de selección o dynpro:

La persistencia de ABAP2UI5 se denomina tabla de borrador, aunque no es completamente igual a la que conoce de RAP. Los borradores de ABAP2UI5 no son específicos del tipo, simplemente persisten en la clase de la aplicación de forma genérica. Por lo tanto, no hay trabajo adicional en la creación de tablas de borrador mecanografiadas, todo funciona automáticamente en segundo plano.

Los borradores son muy útiles para los resultados intermedios, pero tal vez no exagere con esta posibilidad. No es buena idea construir cadenas interminables de apps guardándose entre sí en atributos o intentar salvar millones de entradas en tablas internas. Pero, por supuesto, este tampoco es un buen estilo de programación en otros contextos. Por otro lado, el servidor ABAP y la base de datos son muy potentes, por lo que guardar tablas internas con, por ejemplo, miles de entradas no es un problema.

Pero no olvide borrar la tabla Z2UI5_T_DRAFT de vez en cuando, de lo contrario se llenará.

Esa fue la primera parte de la introducción al Proyecto ABAP2UI5. Siéntase libre de instalar este proyecto y probar los ejemplos y demostraciones. Para noticias y mejoras sigue este proyecto en Gorjeo o echa un vistazo a la repositorio GitHub de vez en cuando.

En la próxima publicación del blog, usaremos ABAP2UI5 para enviar modelos de datos profundos a la interfaz y desarrollar aplicaciones que muestren listas y tablas.

Que piensas de esta aproximación? Siéntase libre de compartir sus comentarios e ideas.

¡Gracias por leer!






ABAPAbap2ui5AppsdesarrollopuroUI5

Artículos relacionados


Technical Articles
Diseño de cuadrícula confiable en SAP Build Apps
SA Repair  ·  Technical Articles
Reparación de SA: activación con SAP BTP Graph y Build Apps
Programming
Por qué debería crear una guía de estilo de código para proyectos de desarrollo
Guía de solución de problemas de control de versiones y transporte (VNT):
Previo
ABAP2UI5 – Salida de Listas y Tablas, Barra de Herramientas y Editable (2/3)
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.