Para la app móvil puede surgir la necesidad de crear una página personalizada en la que dispongamos de una serie de botones enlazados con acciones de Business central:
- Mostrar la lista de productos
- Ver una pantalla de configuración
- Mostrar otra página personalizada, por ejemplo un calendario con la planificación de fabricación, esto lo veremos en un post más adelante
- etc.
En Business central estamos limitados a las acciones de la barra inferior, pilas o elementos con un link, que no es poco ... pero ¿y si dispusiéramos de la opción de añadir botones a voluntad?
Creando pantalla con botones
Para este post voy a utilizar algo que seguro que nos suena o nos es familiar: Bootstrap
Bootstrap ya dispone de lo necesario para no tener que preocuparnos de si un elemento web, un botón en nuestro caso, se ajusta bien a la página junto con otros, o si se recorta, etc. en resumen, si disponemos de una fila de 5 botones alineados de izquierda a derecha y cambiamos el tamaño de la pantalla y esa disposición no se puede mostrar sin cortarse, automáticamente los botones que no quepan se mostrarán en otra lÃnea. Lo que se conoce como responsivo.
A mayores, nuestros botones dispondrán de un icono y cómo tampoco nos vamos a volver locos diseñando un icono, luego otro y otro que mantengan el mismo "tema", tamaños, etc. utilizaremos unas fuentes llamadas fontawesome.
Si queréis ampliar información, aquà dejo link a wikipedia de Bootstrap
Bootstrap ya dispone de lo necesario para no tener que preocuparnos de si un elemento web, un botón en nuestro caso, se ajusta bien a la página junto con otros, o si se recorta, etc. en resumen, si disponemos de una fila de 5 botones alineados de izquierda a derecha y cambiamos el tamaño de la pantalla y esa disposición no se puede mostrar sin cortarse, automáticamente los botones que no quepan se mostrarán en otra lÃnea. Lo que se conoce como responsivo.
A mayores, nuestros botones dispondrán de un icono y cómo tampoco nos vamos a volver locos diseñando un icono, luego otro y otro que mantengan el mismo "tema", tamaños, etc. utilizaremos unas fuentes llamadas fontawesome.
Si queréis ampliar información, aquà dejo link a wikipedia de Bootstrap
Y aquà link a los iconos fonawesome, a fecha de este post, en versión 6.5.1 (filtrados a sólo los gratuitos)
Mirando en el último link, vamos a localizar algunos iconos en fontawesome para nuestra pantalla, por ejemplo:
- una lista de productos, encontramos el icono list y pulsando sobre él aparece el código html a utilizar
copiamos el código y lo reservamos para luego <i class="fa-solid fa-list"></i> - localizamos el icono calendar-days y repetimos la operación
<i class="fa-regular fa-calendar-days"></i> - print: <i class="fa-solid fa-print"></i>
- truck: <i class="fa-solid fa-truck"></i>
- industry: <i class="fa-solid fa-industry"></i>
- ...
El resultado que buscamos, con los iconos elegidos es algo similar a esto:
y trasladando el resultado a cómo lo verÃamos en un móvil, por ejemplo:
Como vemos, los botones se muestran todos seguidos en la misma fila, pero al cambiar de vista a una más pequeña (la del móvil) se ha ajustado sólo a 2 lÃneas de botones sin necesidad de controlar esto mediante código.
Vamos a ver cómo hacer todo esto, explicaremos algunos conceptos y de paso cambiaremos algunos colores.
Vamos a ver cómo hacer todo esto, explicaremos algunos conceptos y de paso cambiaremos algunos colores.
Primero crearemos un carpeta llamada Addin en la que crearemos un fichero llamado buttons.al con este contenido:
controladdin buttons
{
MinimumHeight = 600;
MinimumWidth = 200;
RequestedHeight = 600;
RequestedWidth = 200;
HorizontalShrink = true;
HorizontalStretch = true;
VerticalShrink = true;
VerticalStretch = true;
StartupScript = './Addin/startup.js';
Scripts = 'https://code.jquery.com/jquery-3.7.1.min.js', 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.min.js';
StyleSheets = './Addin/buttons.css', 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css';
event buttonclick(data: Text);
event OnStartup();
procedure loaddata(data: Text);
}
como vemos, el addin arranca un un fichero javascript startup.js y utilizamos una página de estilos local: buttons.css, el resto de elementos necesarios se descarga de cdn, en el código pongo enlaces a la última versión a fecha de este post.
Ahora creamos un fichero con el estilo para nuestros botones llamado buttons.css
.btn-sq-lg {
width: 90px !important;
height: 120px !important;
margin-right: 10px;
margin-top: 5px;
font-size: small;
}
En él estamos indicando altura, anchura y separación entre los botones además del tamaño de la fuente del texto, se puede ajustar a las necesidades sin problema ya que es muy sencillo de entender.
Ahora crearemos el fichero javascript que controla los botones: los muestra y nos informa del click en ellos, startup.js
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('OnStartup')
window.loaddata = function (data) {
var iframe = document.getElementById('controlAddIn');
iframe.innerHTML = data;
var bootstraps = iframe.querySelectorAll('a');
bootstraps.forEach(function(bootstrap) {
bootstrap.addEventListener('click', function() {
var bootId = this.id;
console.log('Pulsado ' + bootId);
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('buttonclick',[bootId]);
});
});
}
Aquà observamos como cargamos el código recibido en la variable data, que pasaremos desde Business central y luego localizamos todos los botones y le añadimos una acción en el evento click, en este caso que nos muestre en consola el nº del botón pulsado y que devuelva a Business central en nº de botón pulsado. Asà sabremos qué botón se ha pulsado y podremos ejecutar desde Business central la acción pertinente.
Por último la página que mostraremos en la aplicación móvil, creamos una nueva página de tipo card
page 50400 "Button Test"
{
ApplicationArea = All;
Caption = 'Prueba botones';
PageType = Card;
UsageCategory = Tasks;
layout
{
area(content)
{
usercontrol(botonera; buttons)
{
trigger OnStartup()
begin
SetBootstrapButtonData();
end;
trigger buttonclick(data: Text)
begin
case data of
'1':
SetBootstrapButtonData();
'2':
SetBootstrapButtonData2();
'3':
SetBootstrapButtonData3();
else
Message('Pulsado botón ' + data);
end;
end;
}
}
}
var
InitDiv: Label '<div class="container"><div class="row"><div class="col-lg-12"><p>';
ButtonSource: Label '<a href="#" id="%1" class="btn btn-sq-lg btn-primary"><i class="fas %2 fa-2x"></i><br/><br/>%3<br>%4</a>';
ButtonSource2: Label '<a href="#" id="%1" class="btn btn-sq-lg btn-success"><i class="fas %2 fa-2x"></i><br/><br/>%3<br>%4</a>';
ButtonSource3: Label '<a href="#" id="%1" class="btn btn-sq-lg btn-info"><i class="fas %2 fa-2x"></i><br/><br/>%3<br>%4</a>';
EndDiv: Label '</p></div></div>';
local procedure SetBootstrapButtonData()
var
TextBuilder: TextBuilder;
begin
TextBuilder.Append(InitDiv);
TextBuilder.Append(StrSubstNo(ButtonSource, '1', 'fa-list', 'Lista', 'productos'));
TextBuilder.Append(StrSubstNo(ButtonSource, '2', 'fa-calendar-days', 'Planif.', 'producción'));
TextBuilder.Append(StrSubstNo(ButtonSource, '3', 'fa-print', 'Imprimir', 'etiquetas'));
TextBuilder.Append(StrSubstNo(ButtonSource, '4', 'fa-truck', 'Ver carga', 'camión'));
TextBuilder.Append(StrSubstNo(ButtonSource, '5', 'fa-industry', 'Comenzar', 'picking'));
TextBuilder.Append(EndDiv);
CurrPage.botonera.loaddata(TextBuilder.ToText());
end;
local procedure SetBootstrapButtonData2()
var
TextBuilder: TextBuilder;
begin
TextBuilder.Append(InitDiv);
TextBuilder.Append(StrSubstNo(ButtonSource2, '1', 'fa-list', 'Lista', 'productos'));
TextBuilder.Append(StrSubstNo(ButtonSource2, '2', 'fa-calendar-days', 'Planif.', 'producción'));
TextBuilder.Append(StrSubstNo(ButtonSource2, '3', 'fa-print', 'Imprimir', 'etiquetas'));
TextBuilder.Append(StrSubstNo(ButtonSource2, '4', 'fa-truck', 'Ver carga', 'camión'));
TextBuilder.Append(StrSubstNo(ButtonSource2, '5', 'fa-industry', 'Comenzar', 'picking'));
TextBuilder.Append(EndDiv);
CurrPage.botonera.loaddata(TextBuilder.ToText());
end;
local procedure SetBootstrapButtonData3()
var
TextBuilder: TextBuilder;
begin
TextBuilder.Append(InitDiv);
TextBuilder.Append(StrSubstNo(ButtonSource3, '1', 'fa-list', 'Lista', 'productos'));
TextBuilder.Append(StrSubstNo(ButtonSource3, '2', 'fa-calendar-days', 'Planif.', 'producción'));
TextBuilder.Append(StrSubstNo(ButtonSource3, '3', 'fa-print', 'Imprimir', 'etiquetas'));
TextBuilder.Append(StrSubstNo(ButtonSource3, '4', 'fa-truck', 'Ver carga', 'camión'));
TextBuilder.Append(StrSubstNo(ButtonSource3, '5', 'fa-industry', 'Comenzar', 'picking'));
TextBuilder.Append(EndDiv);
CurrPage.botonera.loaddata(TextBuilder.ToText());
end;
}
Al iniciar el control cargamos los botones, están numerados del 1 al 5, con el nombre de los iconos que hemos copiado anteriormente de fontawesome y utilizando una plantilla de lÃnea rellena en el label ButtonSource
Al pulsar en el botón 1: Lista productos carga los botones con esa plantilla, al pulsar el botón 2: Planif. producción carga los mismos botones en color verde, el botón 3 produce el mismo resultado en un tono de azul más claro y el resto muestra un mensaje con el nº de botón pulsado
Respecto a los colores de los botones, en este link, podemos ver las distintas opciones.
Propongo 3 opciones como ejemplo para poder ver las distintas posibilidades, pero vemos que hay varias más.
Respecto a los colores de los botones, en este link, podemos ver las distintas opciones.
Propongo 3 opciones como ejemplo para poder ver las distintas posibilidades, pero vemos que hay varias más.
Ahora restarÃa añadir los botones que necesitemos, si queremos separarlos por lÃneas, es decir, bloques de 3 por ejemplo, o de 2, ... deberÃamos encapsular las lÃneas de esos 3 botones en un div, por ejemplo en el código tenemos 5 botones, vamos a poner 3 y 2 al pulsar el botón 2 y llamar a la función SetBootstrapButtonData2
local procedure SetBootstrapButtonData2()
var
TextBuilder: TextBuilder;
begin
TextBuilder.Append(InitDiv);
TextBuilder.Append('<div>');
TextBuilder.Append(StrSubstNo(ButtonSource2, '1', 'fa-list', 'Lista', 'productos'));
TextBuilder.Append(StrSubstNo(ButtonSource2, '2', 'fa-calendar-days', 'Planif.', 'producción'));
TextBuilder.Append(StrSubstNo(ButtonSource2, '3', 'fa-print', 'Imprimir', 'etiquetas'));
TextBuilder.Append('</div><div>');
TextBuilder.Append(StrSubstNo(ButtonSource2, '4', 'fa-truck', 'Ver carga', 'camión'));
TextBuilder.Append(StrSubstNo(ButtonSource2, '5', 'fa-industry', 'Comenzar', 'picking'));
TextBuilder.Append('</div>');
TextBuilder.Append(EndDiv);
CurrPage.botonera.loaddata(TextBuilder.ToText());
end;
Vemos cómo los botones 1 al 3 están en un bloque div y los otros 2 botones en otro bloque div.
El resultado es el siguiente:
Carga normal o pulsando el botón 1 (lista productos)
Carga pulsando el botón 2 (planif. producción)
Y por último nos faltarÃa añadir las acciones correspondientes a cada uno de los botones una vez los hayamos puesto en nuestra pantalla.
Espero que os sirve de ayuda.
Espero que os sirve de ayuda.
Como siempre el código en github
Publicar un comentario