Skip to content

Status bar ​

statusBar: true shows a bar below the grid with the number of rows and – like in a spreadsheet – the count, sum, average, minimum and maximum of the selected cells.

vue
<template>
  <Datagrid :columns="columns" :rows="rows" :options="options" />
</template>

<script setup lang="ts">
import { Datagrid, type ColumnConfig, type GridOptions } from "@datagrid/vue-ui";
import { createEmployees, type Employee } from "./data";

const rows = createEmployees(1000);

const columns: Array<ColumnConfig<Employee>> = [
  { field: "firstName", text: "First name" },
  { field: "lastName", text: "Last name" },
  { field: "department", text: "Department" },
  { field: "salary", text: "Salary", type: "number" },
  { field: "bonus", text: "Bonus", type: "number" },
  { field: "rating", text: "Rating", type: "number" },
];

const options: GridOptions<Employee> = {
  selection: "Cell",
  singleSelect: false,
  statusBar: true,
  defaultColumn: { filterable: true, sortable: true, flex: 1 },
};
</script>
tsx
import { Datagrid, type ColumnConfig, type GridOptions } from "@datagrid/react-ui";
import { createEmployees, type Employee } from "../data";

const rows = createEmployees(1000);

const columns: Array<ColumnConfig<Employee>> = [
  { field: "firstName", text: "First name" },
  { field: "lastName", text: "Last name" },
  { field: "department", text: "Department" },
  { field: "salary", text: "Salary", type: "number" },
  { field: "bonus", text: "Bonus", type: "number" },
  { field: "rating", text: "Rating", type: "number" },
];

const options: GridOptions<Employee> = {
  selection: "Cell",
  singleSelect: false,
  statusBar: true,
  defaultColumn: { filterable: true, sortable: true, flex: 1 },
};

export default function StatusBar() {
  return <Datagrid columns={columns} rows={rows} options={options} />;
}

Select a range of cells (drag or Shift + click) or filter a column to see the values change.

Items ​

statusBar is true (all items) or an object with the items to show in this order:

ts
statusBar: { items: ["rows", "sum", "avg"] }
ItemShowsVisible when
rowsnumber of rows; with active filters filtered of total, e.g. Rows: 12 of 1,000always
selectednumber of selected rowsrows are selected (selection: "Row")
countnumber of selected cellsmore than one cell is selected
sumsum of the numeric values of the selected cellsmore than one cell is selected and it contains numbers
avgaverage of the numeric valuesas sum
minsmallest numeric valueas sum
maxlargest numeric valueas sum
  • Only cell values of type number are aggregated, text cells and empty cells are ignored (but counted by count). The values are the raw cell values, not the formatted ones.
  • The cell aggregations require selection: "Cell". Use singleSelect: false so the user can select ranges.
  • The rows are counted without group rows. With server side data the total comes from the server.
  • The labels are translated with the grid locale (keys status_rows, status_filtered, status_selected, agg_count, agg_sum, …) and the numbers are formatted with the locale and at most two fraction digits.

The status bar is updated when the selection, the data or the filters change.

Custom status bar ​

The content of the status bar can be rendered by the application. It receives

ParameterDescription
itemsthe visible items as { id, label, value } with translated label and formatted value (as configured with statusBar.items)
infothe raw numbers, see below
apithe grid api

Use the statusbar slot:

vue
<Datagrid :options="{ statusBar: true, selection: 'Cell' }" ...>
  <template #statusbar="{ items, info, api }">
    {{ info.filteredRows }} rows
  </template>
</Datagrid>

Use the renderStatusBar prop:

tsx
<Datagrid
  options={{ statusBar: true, selection: "Cell" }}
  renderStatusBar={({ items, info, api }) => <>{info.filteredRows} rows</>}
/>
vue
<template>
  <Datagrid :columns="columns" :rows="rows" :options="options">
    <template #statusbar="{ items, info, api }">
      <span class="status-custom-rows">
        {{ info.filteredRows.toLocaleString() }} of {{ info.totalRows.toLocaleString() }} employees
      </span>
      <template v-if="info.cellCount > 1">
        <span v-for="item in items" :key="item.id" class="status-custom-pill">
          {{ item.label }} <strong>{{ item.value }}</strong>
        </span>
        <button class="status-custom-clear" @click="api.deselectAll()">Clear</button>
      </template>
      <span v-else>Select cells to see sum and average</span>
    </template>
  </Datagrid>
</template>

<script setup lang="ts">
import { Datagrid, type ColumnConfig, type GridOptions } from "@datagrid/vue-ui";
import { createEmployees, type Employee } from "./data";

const rows = createEmployees(1000);

const columns: Array<ColumnConfig<Employee>> = [
  { field: "firstName", text: "First name" },
  { field: "lastName", text: "Last name" },
  { field: "department", text: "Department" },
  { field: "salary", text: "Salary", type: "number" },
  { field: "bonus", text: "Bonus", type: "number" },
  { field: "rating", text: "Rating", type: "number" },
];

const options: GridOptions<Employee> = {
  selection: "Cell",
  singleSelect: false,
  // items passed to the slot
  statusBar: { items: ["sum", "avg"] },
  defaultColumn: { filterable: true, sortable: true, flex: 1 },
};
</script>

<style>
.status-custom-rows {
  margin-right: auto;
}

.status-custom-pill {
  padding: 0 8px;
  border-radius: 10px;
  background: var(--vp-c-brand-soft, #e6f4ec);
  color: var(--ut-color);
}

.status-custom-clear {
  border: none;
  background: none;
  color: var(--vp-c-brand-1, #2e9e6e);
  cursor: pointer;
}
</style>
tsx
import { Datagrid, type ColumnConfig, type GridOptions } from "@datagrid/react-ui";
import { createEmployees, type Employee } from "../data";

const rows = createEmployees(1000);

const columns: Array<ColumnConfig<Employee>> = [
  { field: "firstName", text: "First name" },
  { field: "lastName", text: "Last name" },
  { field: "department", text: "Department" },
  { field: "salary", text: "Salary", type: "number" },
  { field: "bonus", text: "Bonus", type: "number" },
  { field: "rating", text: "Rating", type: "number" },
];

const options: GridOptions<Employee> = {
  selection: "Cell",
  singleSelect: false,
  // items passed to renderStatusBar
  statusBar: { items: ["sum", "avg"] },
  defaultColumn: { filterable: true, sortable: true, flex: 1 },
};

export default function StatusBarCustom() {
  return (
    <>
      <Datagrid
        columns={columns}
        rows={rows}
        options={options}
        renderStatusBar={({ items, info, api }) => (
          <>
            <span className="status-custom-rows">
              {info.filteredRows.toLocaleString()} of {info.totalRows.toLocaleString()} employees
            </span>
            {info.cellCount > 1 ? (
              <>
                {items.map((item) => (
                  <span key={item.id} className="status-custom-pill">
                    {item.label} <strong>{item.value}</strong>
                  </span>
                ))}
                <button className="status-custom-clear" onClick={() => api.deselectAll()}>
                  Clear
                </button>
              </>
            ) : (
              <span>Select cells to see sum and average</span>
            )}
          </>
        )}
      />
      <style>{`
        .status-custom-rows {
          margin-right: auto;
        }

        .status-custom-pill {
          padding: 0 8px;
          border-radius: 10px;
          background: var(--vp-c-brand-soft, #e6f4ec);
          color: var(--ut-color);
        }

        .status-custom-clear {
          border: none;
          background: none;
          color: var(--vp-c-brand-1, #2e9e6e);
          cursor: pointer;
        }
      `}</style>
    </>
  );
}

The option statusBar must still be set, it enables the bar. The bar element (.ut-status-bar) is a flex container, so the rendered elements are laid out in a row.

API ​

ts
api.getStatusBarInfo();
// {
//   totalRows: 1000,     // rows without filters
//   filteredRows: 245,   // rows matching the filters
//   selectedRows: 0,     // selected rows (row selection)
//   cellCount: 6,        // selected cells (cell selection)
//   sum: 412345,         // aggregations of the numeric selected cells,
//   avg: 68724.17,       // undefined if no numbers are selected
//   min: 38001,
//   max: 121400,
// }

api.getStatusBarItems();
// [{ id: "rows", label: "Rows", value: "245 of 1,000" }, { id: "count", label: "Count", value: "6" }, ...]

getStatusBarInfo() works without the status bar, e.g. to show the numbers somewhere else in the application. getStatusBarItems() returns an empty array if statusBar is not set.

Styling ​

ClassElement
.ut-status-barthe bar
.ut-status-bar__iteman item of the default status bar
.ut-status-bar__label, .ut-status-bar__valuelabel and value of an item

Released under the ISC License.