Lattice Grid Buy a licence

demo D163

Line, area, bar and scatter in Vue

The cartesian types, one dataset

type: 'line' · 'step' · 'area' · 'bar' · 'combo' · 'pareto'

This shows the cartesian chart types, line, step, area, bar, combo and pareto, drawn from one dataset. It lets you compare how each shape reads the same numbers, so you can pick the one that tells your story clearest. The line chart also emphasises one series over the rest, by weight rather than only by colour.

Building…
Loading a live grid…

This is the Vue 3 version. A createLatticeGrid component takes the configuration through v-bind, and reactive data flows straight into the grid, so it updates the way the rest of your Vue app does.

The configuration

<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.min.css">
<style>
  #charts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
  #charts > div { height: 180px; }
  #grid { margin-top: 14px; }
  #grid > div { height: 340px; }
</style>
<div id="app"></div>

<script type="module">
  import * as Vue from 'https://esm.sh/vue@3/dist/vue.esm-browser.prod.js';
  import { createGrid } from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.esm.min.js';
  import createLatticeGrid from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/modules/vue.esm.min.js';
  import { createChart } from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/modules/charts.esm.min.js';

  const LatticeGrid = createLatticeGrid({ vue: Vue, createGrid });

  Vue.createApp({
    components: { LatticeGrid },
    data() {
      return {
        config: {
          rowKey: 'id',
          // A bar or horizontal bar with no series of its own takes its colour
          // from these budget rules, one legend entry per rule.
          formatting: {
            charge: [
              { id: 'under', label: 'Under budget', when: { op: 'lt', value: 200000 }, style: { background: '#1a7f37', color: '#fff' } },
              { id: 'near', label: 'Near budget', when: { op: 'lt', value: 225000 }, style: { background: '#b26a00', color: '#fff' } },
              { id: 'over', label: 'Over budget', when: { op: 'gte', value: 225000 }, style: { background: '#c02c38', color: '#fff' } },
            ],
          },
          columns: [
            { field: 'circuit', title: 'Circuit', layout: { width: 180 } },
            { field: 'region', title: 'Region', filter: { type: 'set' } },
            { field: 'status', title: 'Status', filter: { type: 'set' } },
            { field: 'bandwidth', title: 'Bandwidth', type: 'number' },
            { field: 'utilisation', title: 'Utilisation', type: 'number', format: { decimals: 1, suffix: '%' } },
            { field: 'charge', title: 'Monthly charge', type: 'number',
              format: { style: 'currency', currency: 'GBP' }, total: 'sum' },
          ],
          rows,
        },
      };
    },
    mounted() {
      // The component exposes the live grid via a template ref. Every chart reads
      // that one instance, so all ten redraw whenever the grid is sorted or
      // filtered: one dataset, ten encodings.
      const grid = this.$refs.grid.grid();
      createChart({ grid, container: '#line',          type: 'line',          x: 'region', y: 'charge' });
      createChart({ grid, container: '#step',          type: 'step',          x: 'region', y: 'charge' });
      createChart({ grid, container: '#area',          type: 'area',          x: 'region', y: 'charge' });
      // rangeArea draws the min to max band of the measure at each point.
      createChart({ grid, container: '#rangeArea',     type: 'rangeArea',     x: 'region', y: 'charge' });
      createChart({ grid, container: '#bar',           type: 'bar',           x: 'region', y: 'charge' });
      createChart({ grid, container: '#horizontalBar', type: 'horizontalBar', x: 'region', y: 'charge', labels: true });
      createChart({ grid, container: '#scatter',       type: 'scatter',       x: 'utilisation', y: 'charge' });
      createChart({ grid, container: '#bubble',        type: 'bubble',        x: 'utilisation', y: 'charge', size: 'charge' });
      // combo mixes marks on two axes: bars of total charge and a line of mean bandwidth.
      createChart({ grid, container: '#combo',         type: 'combo',         x: 'region',
        measures: [{ col: 'charge', fn: 'sum', type: 'bar', axis: 'left' },
                   { col: 'bandwidth', fn: 'mean', type: 'line', axis: 'right' }] });
      // pareto sorts the bars and draws the cumulative line.
      createChart({ grid, container: '#pareto',        type: 'pareto',        x: 'status', y: 'charge' });
    },
    template: `
      <div id="charts">
        <div id="line"></div>
        <div id="step"></div>
        <div id="area"></div>
        <div id="rangeArea"></div>
        <div id="bar"></div>
        <div id="horizontalBar"></div>
        <div id="scatter"></div>
        <div id="bubble"></div>
        <div id="combo"></div>
        <div id="pareto"></div>
      </div>
      <div id="grid"><lattice-grid ref="grid" v-bind="config" /></div>
    `,
  }).mount('#app');
</script>