• Renderizado en HTML

  • Renderizado en PDF

  • Renderizado en Mails

  • Renderizado en CSV

Diagram DSL permite dibujar rápidamente diagramas de barras (bar), áreas (area), circulares (pie), dispersión (scatter), líneas (line), cajas y bigotes (whiskers) y líneas de tiempo (timeline), posiblemente combinados (mixed), ya sea rasterizados en formato PNG o en formato SVG.

En un bloque, un diagrama se añade mediante diagram, que recibe un UiDiagramSpecifier o un MethodClosure que devuelva uno, o mediante diagramFilter para asociarlo con un filtro.

Ejemplos de gráficos

Barras (Bar)

Example 1. Gráfico de barras
Ejemplo de código de gráfico de barras
private static UiDiagramSpecifier barDiagram(boolean isStacked) {
    new UiDiagramSpecifier().ui {
        bar(isStacked, {
            labels "T1", "T2", "T3", "T4"
            dataset 'Truc1', 1.0, 2.0, 1.0, 4.0
            dataset 'Truc2', 2.0, 0.1, 1.0, 0.0
            dataset 'Truc3', 2.0, 0.1, 1.0, 1.0
        })
    }
}
Resultado

diag dsl bar

Líneas (Line)

Example 2. Gráfico de líneas
Ejemplo de código de gráfico de líneas
diagram new UiDiagramSpecifier().ui({
    line {
        labels 1.5, 3, 4.4, 5, 7.8, 8
        dataset "client", 10.0, 20.1, 30.0
        dataset "admin", 5.0, 7.0
        dataset "other", 1.0, 2.0, 3.0, 4.0, 5.0, 6.0
    }
})
Resultado

diag dsl line

Circular (Pie)

Example 3. Gráfico circular
Ejemplo de código de gráfico circular
private static UiDiagramSpecifier pieDiagram(boolean hasSlice) {
    new UiDiagramSpecifier().ui({
        pie(hasSlice, {
            labels "Pie"
            dataset("cli", 1.47)
            dataset("client", 0.28)
            dataset("client1", 0.1)
            dataset("client2", 1.45)
            dataset("client3", 0.05)
            dataset("client31", 0.05)
            dataset("client32", 0.05)
            dataset("c33", 0.05)
            dataset("client311", 0.05)
            dataset("client312", 0.05)
            dataset("client313", 0.05)
            dataset("client4", 0.8)
            dataset("client5", 2.1)
            dataset("client55", 0.1)
            dataset("client555", 0.2)
            dataset("client5555", 0.3)
            dataset("client55555", 0.3)
            dataset("admin", 1.6)
            dataset("test1", 0.05)
        })
    })
}
Resultado

diag dsl pie

Cajas y bigotes (Whiskers)

Example 4. Gráfico de cajas y bigotes
Ejemplo de código de cajas y bigotes
diagram new UiDiagramSpecifier().ui({
    whiskers {
        labels "T1", "T2", "T3", "T4"

        dataset 'Truc1', {
            boxData 1.0, 2.0, 3.0, 3.5, 4.0, 4.5, 5.0
            boxData 1.5, 2.5, 3.5, 6.0, 7.0, 8.0, 9.0
            boxData 2.0, 2.0, 2.1, 2.5, 5.5, 5.6, 6.7
            boxData 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3
        }
        dataset 'Truc2', {
            boxData 0.5, 1.0, 1.1, 1.2, 1.3, 2.0, 5.5
            boxData 0.5, 1.0, 1.1, 1.2, 1.3, 2.0, 5.5
            boxData 0.5, 1.0, 1.1, 1.2, 1.3, 2.0, 5.5
            boxData 0.5, 1.0, 1.1, 1.2, 1.3, 2.0, 5.5
        }
    }
})
Resultado

diag dsl whiskers

Línea de tiempo (Timeline)

Example 5. Gráfico de línea de tiempo
Ejemplo de código de línea de tiempo
diagram new UiDiagramSpecifier().ui({
    timeline {
        SimpleDateFormat format = new SimpleDateFormat('yyyy-MM-dd')
        dataset 'Truc1', {
            periodData format.parse('2025-06-12'), format.parse('2025-07-08'), "Period1"
            periodData format.parse('2025-07-08'), format.parse('2025-07-21'), "Period2"
            periodData format.parse('2025-07-21'), format.parse('2025-08-30'), "Period3"
        }
        dataset 'Truc2', {
            periodData format.parse('2025-06-20'), format.parse('2025-06-25'), "Period1"
            periodData format.parse('2025-07-01'), format.parse('2025-07-21'), "Period2"
        }
    }
})
Resultado

diag dsl timeline

Combinado (Mixed)

Otros tipos de diagramas pueden anidarse dentro del closure de un diagrama. Comparten las etiquetas del eje X y la leyenda, teniendo cada tipo anidado su propio eje Y, coloreado igual que sus conjuntos de datos (dataset).

Example 6. Gráfico combinado
Ejemplo de código de gráfico combinado
diagram new UiDiagramSpecifier().ui {
    bar {                                                           (1)
        labels 'W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'W7', 'W8'
        dataset 'Line A', 55.0, 62.0, 58.0, 70.0, 74.0, 61.0, 80.0, 77.0
        dataset 'Line B', 40.0, 48.0, 44.0, 58.0, 61.0, 57.0, 70.0, 65.0
        line {                                                      (2)
            dataset 'Scrap rate (%)', 2.1, 1.8, 2.5, 1.6, 1.4, 2.9, 1.2, 1.5
        }
        scatter {                                                   (3)
            dataset 'Downtime (h)', 4.0, 6.0, 3.0, 8.0, 5.0, 2.0, 7.0, 4.0
        }
        option DiagramOption.builder
                .setTitle('Weekly production')
                .build()
    }
}
1 Diagrama principal que define las etiquetas del eje X (aquí un gráfico de barras apiladas)
2 Línea anidada, dibujada sobre las barras con su propio eje Y a la derecha
3 Dispersión anidada, con su propio eje Y a la izquierda
Resultado

diag dsl mixed

Opciones personalizadas

Ofrecemos varias opciones para que el usuario personalice el gráfico mediante DiagramOption.

Gráfico de barras usando DiagramOption
private static UiDiagramSpecifier barDiagram(boolean isStacked) {
    new UiDiagramSpecifier().ui {
        bar(isStacked, {
            labels "T1", "T2", "T3", "T4"
            dataset 'Truc1', 1.0, 2.0, 1.0, 4.0
            dataset 'Truc2', 2.0, 0.1, 1.0, 0.0
            dataset 'Truc3', 2.0, 0.1, 1.0, 1.0

            option DiagramOption.builder
                    .setTitle("This is a Bar chart !")
                    .hideLegend()
                    .showDataCount()
                    .setKeyColors(Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN)
                    .setClickAction(Pr2Controller.&onclickBar as MethodClosure)
                    .setResolution(DiagramResolution.DEFAULT_2K)
                    .build()
        })
    }
}
Resultado

diag dsl bar option

Opciones disponibles:

  • setTitle: título del diagrama

  • hideLegend: las leyendas se muestran de forma predeterminada

  • showDataCount: muestra los valores en el diagrama (ocultos de forma predeterminada)

  • setKeyColors: colores de cada conjunto de datos (7 colores de forma predeterminada)

  • setClickAction: acción llamada al hacer clic en una forma; recibe los parámetros key (nombre del conjunto de datos), x e y, además del id y los parámetros indicados (véase Diagrama interactivo (Clickable Diagram))

  • setResolution: la resolución predeterminada es SVG: 960x540, desde DEFAULT_540P hasta DEFAULT_4K

  • setXLabelDateFormat: véase Diferentes tipos de etiquetas en el eje X (xLabels)

  • setMaxDataNumberToShowByDefault: limita el número de datos mostrados antes de hacer zoom

  • showTodayLine: solo para líneas de tiempo, dibuja una línea en la fecha actual

Diagrama interactivo (Clickable Diagram)

Cuando se configura una acción de clic, al hacer clic en una forma (barra, punto, sector, caja, periodo…​) se llama a la acción mediante Ajax. La acción puede devolver un bloque, normalmente una ventana modal, o una página completa que se abrirá en una nueva pestaña.

Apertura de una ventana modal al hacer clic en una barra
def salesPerMonth() {
    taackUiService.show(new UiBlockSpecifier().ui {
        diagram new UiDiagramSpecifier().ui {
            bar false, {
                labels 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'
                dataset 'Bikes', 12.0, 18.0, 9.0, 21.0, 25.0, 30.0
                dataset 'Scooters', 7.0, 5.0, 11.0, 8.0, 14.0, 12.0
                option DiagramOption.builder
                        .setTitle('Units sold per month')
                        .setClickAction(SalesController.&salesDetail as MC,  (1)
                                [year: 2026])
                        .build()
            }
        }
    }, buildMenu())
}

def salesDetail(String key, String x, String y, Integer year) {         (2)
    int units = new BigDecimal(y).intValue()
    Map<String, Integer> orders = [                                     (3)
            'Acme Corp': units.intdiv(2) as Integer,
            'Globex'   : units.intdiv(3) as Integer,
            'Initech'  : units - units.intdiv(2) - units.intdiv(3)
    ]
    taackUiService.show(new UiBlockSpecifier().ui {
        modal {                                                         (4)
            show new UiShowSpecifier().ui {
                field 'Product', key
                field 'Month', "$x $year".toString()
                field 'Units sold', y
            }
            table new UiTableSpecifier().ui {
                header {
                    label 'Order'
                    label 'Customer'
                    label 'Units'
                }
                orders.eachWithIndex { Map.Entry<String, Integer> o, int i ->
                    row {
                        rowField "SO-$year-$x-${i + 1}".toString()
                        rowField o.key
                        rowField o.value
                    }
                }
            }
        }
    })
}
1 Acción llamada al hacer clic, con parámetros opcionales (o un id)
2 key es el nombre del conjunto de datos, x la etiqueta en el eje X e y el valor; year proviene de los parámetros pasados a setClickAction
3 Datos ficticios, normalmente una consulta sobre sus objetos de dominio
4 La acción responde con una ventana modal, mostrada sobre el diagrama
diag dsl click modal
Figure 1. Clic en la barra "Bikes" de mayo

Formas adicionales de programar

Diferentes tipos de etiquetas en el eje X (xLabels)

Las etiquetas del eje X pueden ser de 3 tipos:

  • Cadena (String, discreto)

  • Número (Number, continuo)

  • Fecha (Date, continuo)

diagram new UiDiagramSpecifier().ui({
    line { // X axis: String
        labels "T1", "T2", "T3"
        dataset "test", 10.0, 20.1, 30.0
    }
    line { // X axis: Number
        labels 1.5, 1.7, 3.5
        dataset "test", 10.0, 20.1, 30.0
    }
    line { // X axis: Date
        Date date1 = new Date() // now (2025-02-28 10:55)
        Date date2 = new Date(date1.getTime() + 1000*60*60*2) // 2 hours later
        Date date3 = new Date(date1.getTime() + 1000*60*60*10) // 10 hours later
        labels date1, date2, date3
        dataset "test", 10.0, 20.1, 30.0
        option DiagramOption.builder
                .setXLabelDateFormat(DiagramXLabelDateFormat.HOUR) (1)
                .build()
    }
})
1 DiagramXLabelDateFormat: define el formato de fecha que se mostrará y también la unidad mínima de intervalo (porque el eje X es continuo)

screenshot dsl diagram xLabels type

Segunda forma de indicar las coordenadas de los datos

Se utiliza a menudo para ejes X continuos en los que distintos conjuntos de datos tienen diferentes coordenadas X.

diagram new UiDiagramSpecifier().ui({
    // Normal way: different datasets have same X coordinates
    line {
        labels 1.5, 1.7, 3.5

        // 3 data: (1.5, 10.0), (1.7, 20.1), (3.5, 30.0)
        dataset "test1", 10.0, 20.1, 30.0

        // 3 data: (1.5, 1.0), (1.7, 2.0), (3.5, 3.0)
        dataset "test2", 1.0, 2.0, 3.0
    }

    // Second way: different datasets have different X coordinates
    line {
        // 3 data: (1.5, 10.0), (1.7, 20.1), (3.5, 30.0)
        dataset "test1", [1.5: 10.0, 1.7: 20.1, 3.5: 30.0]

        // 2 data: (1.5, 1.0), (6.1, 2.0)
        dataset "test2", [1.5: 1.0, 6.1: 2.0]
    }
})

screenshot dsl diagram coordinate

DSL para mostrar el recuento de datos a intervalos regulares

Tenemos un gran número de objetos y queremos un diagrama que muestre la cantidad de objetos año por año (o mes por mes / día por día / hora por hora) según el campo dateCreated del objeto.

DSL a utilizar
    /**
     * Group the given dates according to DiagramXLabelDateFormat, then count every group and put the result as data to draw.
     *
     * For example:
     *      Knowing DiagramXLabelDateFormat.MONTH (Defined by {@link #labels(DiagramXLabelDateFormat dateFormat)}),
     *      and being given dates: 2025-01-01, 2025-01-10, 2025-01-20, 2025-02-01, 2025-02-10, 2025-03-01.
     *
     *      So they are divided to 3 groups with their own count: [2025-01: 3, 2025-02: 2, 2025-03: 1].
     *      The groups will be used as data to draw:
     *          - xLabels = ["2025-01", "2025-02", "2025-03"]
     *          - yDataList = [3.0, 2.0, 1.0]
     *
     * @param key
     * @param dates
     */
    void dataset(final String key, final Date... dates)
Código de uso del DSL
diagram new UiDiagramSpecifier().ui({
    List<Claim> claims = Claim.findAll()
    bar {
        dataset "Claim", claims.collect { it.dateCreated } as Date[]
        option DiagramOption.builder
                .setXLabelDateFormat(DiagramXLabelDateFormat.MONTH) // show claim count month-by-month
                .build()
    }
})
Diagrama

screenshot dsl diagram count object

Partes dinámicas (solo en HTML)

Zoom (horizontal)

Coloque el ratón sobre el diagrama y gire la rueda del ratón manteniendo pulsada la tecla CTRL.

  • CTRL + rueda hacia arriba para acercar el zoom.

  • CTRL + rueda hacia abajo para alejar el zoom.

Desplazamiento (horizontal)

Coloque el ratón sobre el diagrama, mantenga pulsado el botón izquierdo del ratón y muévalo horizontalmente.

Los límites mínimo y máximo del desplazamiento están acotados

Descripción emergente (Tooltip)

El valor del gráfico de barras/líneas/…​ no se muestra estáticamente de forma predeterminada. En su lugar, al situar el ratón sobre cualquier forma aparecerá dinámicamente una descripción emergente que muestra toda la información sobre dicha forma.

screenshot dsl diagram tooltip

Leyenda interactiva

Hacer clic en la leyenda de un conjunto de datos permite ocultar o mostrar el conjunto de datos correspondiente.

Jerarquía de símbolos DSL

Diagram
Figure 2. Diagrama de jerarquía de símbolos para Diagram DSL