Cualquier elemento de la interfaz de usuario de una vista Web Dynpro Abap se puede tanto crear como modificar mediante código. De esta manera, existe la posibilidad de modificar dinámicamente el layout WD4A de una vista en tiempo de ejecución.
En este artículo vamos a ver algunas técnicas y métodos para hacer este tipo de modificaciones dinámicas en Web Dynpro Abap.
Layout dinámico en WD4A: wddomodifyview
Lo primero y más importante es hablar del método wddomodifyview. El código fuente para todos los cambios dinámicos tiene que ser definido en este método Hook estándar, ya que es el único método que recibe una referencia válida al nodo raíz de la jerarquía de elementos UI.
El método wddomodifyview es llamado justo antes de que el layout sea renderizado, por lo tanto, se ejecutará siempre que se desencadene un evento.
Principios para modificar dinámicamente WD4A UI
Se deben utilizar los siguientes principios a la hora de realizar manipulaciones dinámicas de UI:
- Sólo se deben realizar manipulaciones de elementos UI cuando no es posible controlar el comportamiento a través de binding con el contexto en tiempo de diseño.
- La manipulación de elementos UI sólo está permitida en el método wddomodifyview.
- wddomodifyview tiene un parámetro booleano llamado first_time, que será abap_true la primera vez que se ejecuta, y abap_false en cualquier otro caso.
- No se debe implementar código que modifica el contexto dentro de wddomodifyview. El contexto debería considerarse como de sólo lectura durante la ejecución de este método.
Modificación del layout WD4A mediante código
El siguiente paso para acceder o crear un elemento UI dinámicamente en WD4A es conseguir una referencia al elemento contenedor.
Este elemento contenedor podría ser RootUIElementContainer, elemento que existe por defecto en todos los controladores de vistas. Para obtener esta referencia, se deben utilizar métodos del parámetro de entrada view. Para acceder a un elemento arbitrario se puede llamar al método get_element(), pasando el ID del elemento como parámetro.
A continuación vemos un ejemplo de cómo coger un elemento UI, en este caso el RootUIElementContainer:
DATA: lr_ui_element TYPE REF TO if_wd_view_element, lr_container TYPE REF TO cl_wd_uielement_container. CHECK first_time = abap_true. *Se coge la referencia al nodo raíz por ID: lr_ui_element = view->get_element( id = 'ROOTUIELEMENTCONTAINER' ). * Cast necesario lr_container ?= lr_ui_element.
Esta acción se puede realizar con cualquier elemento UI que exista en el layout, pasando su correspondiente ID y creando la referencia a su clase de elemento. Para cada elemento UI existe una clase describiendo el elemento existente. Todas estas clases son subclases de CL_WD_UIELEMENT. Estas clases usan la convención de nombres CL_WD_<tipo de elemento>, por ejemplo CL_WD_LABEL o CL_WD_TABLE.
Ahora vamos a mostrar cómo se añadiría un input_field con su etiqueta al nodo raíz. Primero creamos los elementos:
DATA: lr_label TYPE REF TO cl_wd_label, lr_input TYPE REF TO cl_wd_input_field. *se crea un inputField relacionado con un atributo del contexto lr_input = cl_wd_input_field =>new_input_field( bind_value = '<node_name>.<atribute_name>' id = 'INPUT_FIELD_<attribute_name>' ). *se crea una etiqueta para el inputField lr_label = cl_wd_label=>new_label( id = 'LABEL_<attribute_name>' label_for = lr_input->id ).
Una vez creados y antes de añadirlos a un elemento contenedor, se deben ajustar las propiedades del elemento contenedor al que se va a añadir. Esto es especialmente importante en el caso de la propiedad Layout, ya que ésta influencia las propiedades de los elementos hijos.
Para asignar el layout deseado al elemento contenedor, debe ser llamado un método estático de la clase que representa el layout. Todas las clases de layout son sub-clases de CL_WD_LAYOUT. Por lo tanto, en el ejemplo que nos ocupa, en el que queremos añadir un input_field con su etiqueta al nodo raíz haríamos lo siguiente:
*se define el layout data para los elementos creados cl_wd_matrix_head_data=>new_matrix_head_data( element = lr_label ). cl_wd_matrix_data=>new_matrix_data( element = lr_input ).
En este ejemplo se utiliza el tipo de layout MatrixLayout. Es importante que el elemento contenedor donde se van a añadir los elementos tenga el mismo tipo indicado.
Por último, se añaden los elementos creados al contenedor:
lr_container->add_child( the_child = lr_label ). lr_container->add_child( the_child = lr_input ).
Así es como se consigue crear elementos UI por código en Web Dynpro Abap.
Para modificarlos, deberíamos cogerlos de la misma manera que hemos cogido el elemento raíz, y utilizar los diferentes métodos disponibles en las diferentes clases de los elementos.
Por ejemplo, para modificar alguna propiedad, todos tienen un método llamado SET_<nom_propiedad>() por cada propiedad del elemento.
Para más información, se puede acceder a las clases de cada elemento (como hemos comentado CL_WD_<nom_elemento>) o en la ayuda de SAP, donde se encuentran descritos todos los elementos.