Más allá de Style en Business central

 

En las páginas que creamos o extendemos en Business central podemos utilizar la propiedad Style en los campos a resaltar o enfatizar aportándoles otro color o estilo de letra.
Los estilos disponibles son los siguientes:

Incluso podemos utilizar una variable de texto usando StyleExpr y aplicar diferentes estilos condicionalmente, por ejemplo:

page 50001 "Style page"
{
    ApplicationArea = All;
    Caption = 'Style page';
    PageType = List;
    SourceTable = "Integer";
    UsageCategory = Lists;

    layout
    {
        area(Content)
        {
            repeater(General)
            {
                field(ColumnValue; ColumnValue)
                {
                    Caption = 'Valor';
                    StyleExpr = StyleExprtxt;
                    Editable = false;
                }
            }
        }
    }

    trigger OnOpenPage()
    begin
        Rec.SetRange(Number, 1, 100);
    end;

    trigger OnAfterGetRecord()
    begin
        ColumnValue := Random(100);
        if ColumnValue > 50 then
            StyleExprtxt := 'Favorable'
        else
            StyleExprtxt := 'Unfavorable';
    end;

    var
        ColumnValue: Integer;
        StyleExprtxt: Text;
}

Aquí tenemos una página de tipo lista con 100 líneas en las que habrá un número aleatorio entre 1 y 50. Los números por encima de 50 tendrán un estilo con letra en color verde y en rojo el resto.

Resultado:


Esto está bien, como digo, podemos aplicar diferentes estilo condicionalmente por cada campo mostrado.
Pero digamos que esto es sólo una pequeña porción del pastel ... ¿qué ocurre si quiero la tarta entera?

Aplicando estilos más allá de Style

En la imagen vemos que la primera casilla representa un valor 75, acentuado en letra verde + bold.

¿Podríamos aplicar algún otro color?


Unos poquitos más ... del orden de 16^6, es decir, 16.777.217 colores.
Recordemos que 000000 también es un color por lo que 16^6 = 16.777.216 + 1.
Y esto para uno de los 2 colores en juego; cualquier "casilla" dispone de un color de texto más un color de fondo y a mayores podemos añadir efectos como sombras, bordes redondeados, .. .etc.
No debemos olvidar que la representación que observamos de la página que acabamos de crear es una página web y por lo tanto, es manipulable.

Vaya, mis posibilidades aumentan!!!!

Vamos a verlo con un ejemplo.

Necesitamos un addin que crearemos según nuestras necesidades.
Me parece más interesante manipular una página de tipo list que una de tipo card, aunque la lógica se puede aplicar a ambas haciendo pequeñas modificaciones.

Primero crearemos un fichero javascript que será en encargado de "hacer la magia".
Creamos un fichero llamado script.js con el siguiente contenido

Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('ControlAddInReady', null);

window.ChangeColors = function(limit,overcolor,undercolor){
    GridControl = window.parent.document.querySelectorAll('.ms-nav-grid-vertical-container');
    Grid = GridControl[GridControl.length - 1];
    column = Grid.querySelectorAll('td[aria-readonly="true"][tabindex="-1"][data-focusable="true"][data-prev-tabindex="-1"][role="gridcell"]');  
    column.forEach((col) => {              
            const colChild = col.childNodes;            
            if (parseFloat(colChild[0].value) < limit || parseFloat(colChild[0].title) < limit)
            {              
                col.style.backgroundColor = undercolor;                      
                colChild[0].style.backgroundColor = undercolor;                                  
            }
            else
            {
                col.style.backgroundColor = overcolor;                
                col.style.setProperty("color", "black", "important");      
                colChild[0].style.backgroundColor = overcolor;                
                colChild[0].style.setProperty("color", "black", "important");
            };
    });      
}

En este script localizamos el área que contiene el repeater de nuestra página list y el que queremos manipular.
GridControl = window.parent.document.querySelectorAll('.ms-nav-grid-vertical-container');
Como podemos tener abiertas varias pages de Business central y estarán dispuestas por capas una encima de otra, nos olvidamos del resto de posibles páginas tipo list que pueda haber en las capas de detrás y nos centramos en la última o más superficial: 
Grid = GridControl[GridControl.length - 1];
Una vez localizado el control que contiene el repeater, recorremos todas las "celdas" aplicando un cambio de color que estará indicado por la variable limit, si es inferior pondremos el color undercolor y si es superior, overcolor.
column = Grid.querySelectorAll('td[aria-readonly="true"][tabindex="-1"][data-focusable="true"][data-prev-tabindex="-1"][role="gridcell"]');  
    column.forEach((col) => {    

La fila que está seleccionada, el registro actual, será col y el resto de filas colchild[0]
Por último, como el color de la letra viene marcado por los css de Business central, lo modificamos con la propiedad important para que tenga efecto.

Ahora definimos el addin para poder utilizarlo en nuestra página, en este caso lo he llamado Colorize.al

controladdin Colorize
{
    StartupScript = './Objects/script.js';
    RequestedHeight = 1;
    MinimumHeight = 1;
    HorizontalStretch = true;

    event ControlAddinReady();
    procedure ChangeColors(limit: Decimal; overcolor: Text; undercolor: Text);
}

Ya que no vamos a mostrar nada sino que actuaremos sobre el contenedor o ventana padre, le daremos la mínima altura posible, 1 en este caso.
Creamos un trigger que nos indica cuando se inicia el control y una función en la que le pasamos indicaciones del valor de "corte" y los colores si está por encima o por debajo de este valor.

Por último, vamos a modificar un poco la página anterior y vamos a añadir algún que otro "invitado" más para que parezca que hay ambiente 😎:

page 50001 "Style page"
{
    ApplicationArea = All;
    Caption = 'Style page';
    PageType = List;
    SourceTable = "Integer";
    UsageCategory = Lists;

    layout
    {
        area(Content)
        {
            repeater(General)
            {
                field(col1; col1)
                {
                }
                field(col2; col2)
                {
                }
                field(col3; col3)
                {
                }
                field(col4; col4)
                {
                }
                field(col5; col5)
                {
                }
                field(col6; col6)
                {
                }
            }
            group(colores)
            {
                field(limit; limit)
                {
                    Caption = 'Límite separación colores';
                }
                field(overcolor; overcolor)
                {
                    Caption = 'Color por encima del límite';
                }
                field(undercolor; undercolor)
                {
                    Caption = 'Color por debajo del límite';
                }
            }
            usercontrol(Colorize; Colorize)
            {
                trigger ControlAddinReady()
                begin
                    CurrPage.Colorize.ChangeColors(50, 'powderblue', 'red');
                end;
            }

        }
    }
    actions
    {
        area(Processing)
        {
            action(colorchange)
            {
                Caption = 'Aplicar colores y límite';
                Image = Design;

                trigger OnAction()
                begin
                    CurrPage.Colorize.ChangeColors(limit, overcolor, undercolor);
                end;
            }
        }
        area(Promoted)
        {
            actionref(colorchange_promoted; colorchange) { }
        }
    }

    trigger OnOpenPage()
    begin
        Rec.SetRange(Number, 1, 100);
    end;

    trigger OnAfterGetRecord()
    begin
        col1 := Random(100);
        col2 := Random(100);
        col3 := Random(100);
        col4 := Random(100);
        col5 := Random(100);
        col6 := Random(100);
    end;

    var
        col1: Integer;
        col2: Integer;
        col3: Integer;
        col4: Integer;
        col5: Integer;
        col6: Integer;
        limit: Integer;
        overcolor: Text;
        undercolor: Text;
}

Al cargar la página, por defecto marcamos un límite de 50 y aplicamos los colores rojo y azul como vemos en la imagen



Ahora vamos a aplicar unos colores ... cuanto menos ... llamativos!!!!




Es posible trabajar con colores que reconozca el navegador como yellow, black, etc. y también con sus valores hexadecimales:

También podemos redondear las celdas:

        if (parseFloat(colChild[0].value) < limit || parseFloat(colChild[0].title) < limit)
            {              
                col.style.backgroundColor = undercolor;      
                col.style.borderRadius = "10px";        
                colChild[0].style.backgroundColor = undercolor;                
                colChild[0].style.borderRadius = "10px";        
            }




Incluso es posible añadir imágenes en la lista según nuestras necesidades, por ejemplo, en la la 1ª columna, donde aparece la flecha que señala el registro actual:

ColHeader = Grid.querySelectorAll('td[role="rowheader"]');    
    ColHeader.forEach((HeaderContainer) => {
        if (HeaderContainer.childNodes.length == 0)
            {
                const img = document.createElement('img');        
                img.src = "https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b?ver=5c31";
                img.alt = 'Sample Image';
                img.style.Width = '50px';
                img.style.height =  '10px';
                img.style.display = 'block';
                HeaderContainer.appendChild(img);              
            };
        });




El código del ejemplo no es perfecto, ni lo pretende, sólo se pretende mostrar las posibilidades de las que disponemos y que no terminan en la propiedad Style ... tenemos en nuestras manos la posibilidad de hacer muchas más cosas.
Pero como en otros post, lo que hagamos con esto puede ser algo llamativo y resolver la situación o destruir las corneas de alguien con buen gusto o un poco de criterio en diseño 😂😂😂


En esta ocasión el código importante se encuentra en el fichero script.js que está mostrado más arriba con lo que no se subirá a github, lo podéis copiar,. modificar y utilizar a vuestro criterio.

Espero que os haya resultado de utilidad.





Publicar un comentario

Añade comentario (0)

Artículo Anterior Artículo Siguiente