Grid customization and styling

Grid customization and styling beyond CSS

The look and feel of the component can be fully customized by means of CSS. It refers to colors, borders, buttons, pop-ups, and grid cells. But there are cases when just CSS is not enough for pivot table report. For example, when you want to represent the numbers in cells by pictograms showing how ‘good’ or ‘bad’ these numbers are.

Another inquiry, you need to highlight the segment of the table representing sales in Canada. In yet another case, it is required for several report cells to contain hyperlinks to some external data. If you would like to style up entire columns, rows or specific cells based on the data nature, Flexmonster component can suggest you customizeCell function to achieve these goals.

How does it work? customizeCell function can be defined for the instance of the component. It is triggered for each table cell during rendering and it is provided with 2 parameters - cell builder (cell) and cell data object (data). Cell builder contains the default HTML representation of the cell as well as the instruments for its modification. Cell data object contains the information about the cell, about its position on the grid and about the semantics of data being represented by this cell.

The idea is that customizeCell function receives the reference to the cell builder for the particular cell and based on its data object, the function either leaves the cell as-is or modifies it.

Let’s go through 7 use cases when customizeCell helps in achieving visualization goals.

Case 1. Alternating row colors

By default, all data cells have the same background color on the grid. It is a common practice to add shading to alternate rows for making them more readable. This case explains how you can alternate row colors in the Flexmonster grid to automatically highlight every other row in it.

The idea is to specify an additional CSS class with a custom color and this class to each cell that belongs to an even row.

CSS:

#fm-pivot-view #fm-grid-view div.alter {
  background-color: #e1e1e1;
}

The cell data object has rowIndex property that helps to identify whether the row is even or odd. Also, the type of the cell can be checked using type property of the data object. It can be "header" or "value". Type "value" means that the cell is from table area with numbers. In this sample, we want to apply CSS classes only to cells where data.type == "value". The cell builder method addClass() is used to add CSS classes to the cells.

customizeCell:

function customizeCellFunction(cell, data) {
  if (data.type == "value") {
    if (data.rowIndex % 2 == 0) {
      cell.addClass("alter");
    } else {
      return;
    }
  }
}

Here is a live sample: JSFiddle - Alternate row colors

The same approach can be used for alternating column colors.

Case 2. Styling subtotals and grand totals

Highlighting subtotals and grand totals is a brand new option. Moreover, you can style totals in rows and in columns independently. Cell data object has several new properties specifying if the cell is subtotal in compact pivot, subtotal in classic view or grand total:

  • isTotal
  • isTotalRow
  • isTotalColumn
  • isClassicTotalRow
  • isGrandTotal
  • isGrandTotalRow
  • isGrandTotalColumn

Based on the values of these properties in each particular cell, you can add CSS class to the cell using the cell builder.

Let's have a look at the below example. To style subtotals in the classic view, customizeCell adds the fm-total-classic-r CSS class to subtotal cells. Grand totals already have the needed classes, so they are not defined in customizeCell. Try on JSFiddle.

CSS:

#fm-pivot-view #fm-grid-view .fm-total-classic-r {
  background-color: #B2DBBF;
}

customizeCell:

function customizeCellFunction(cell, data) {
  if (data.isClassicTotalRow)
    cell.addClass("fm-total-classic-r");
}

Live sample: JSFiddle - Styling subtotals and grand totals

Case 3. Highlighting cells based on their data

The CellDataObject is an object that contains information about the cell and is used in such methods as getCell(), getSelectedCell(), and the already mentioned customizeCell(). This object has measure, row, and column properties that contain info about the cell's semantics. Let’s examine the usage of these properties through three examples:

3.a. Highlighting a certain member on the grid

This example describes how to highlight cells containing info about a certain member regardless of their position:

const highlightedMembers = {
  "Country": ["Canada", "Germany"],
  "Business Type": ["Warehouse"]
}

function customizeCellFunction(cell, data) {
  if (data.rows) {
    data.rows.forEach(row => {
      if (highlightedMembers[row.hierarchyName] &&
      highlightedMembers[row.hierarchyName].includes(row.caption)) {
        cell.addClass("highlight");
      }
    });
  }
  if (data.columns) {
    data.columns.forEach(column => {
      if (highlightedMembers[column.hierarchyName] &&
      highlightedMembers[column.hierarchyName].includes(column.caption)) {
        cell.addClass("highlight");
      }
    });
  }
}

Then, after the attributes were added, the following CSS selector can be written:

.highlight {
  background-color: #FFB74D !important;
}

Try a live sample on JSFiddle: Highlighting a certain member on the grid.

3.b. Highlighting a certain measure on the grid

This sample is alike to the previous one, but information about now we are highlighting a certain measure as follows:

function customizeCellFunction(cell, data) {
  if (data.measure) {
    cell.attr["measure"] = data.measure.name;
  }
}

Each HTML cell will have a measure attribute, and the following CSS selector will highlight the rows with Price measure:

#fm-pivot-view .fm-grid-view div[measure="Price"] {
  background-color: #B2DBBF;
}

Check on JSFiddle: Highlighting a certain measure on the grid.

3.c. Adding all the semantic info to cell builder attributes

This sample highlights another way of adding all the semantic info to cell builder attributes: Highlighting cells based on their semantic.

Also, it takes into account the position of the hierarchies in rows and columns.

Case 4. Highlighting cells based on their semantics - member, hierarchy, measure

Let us imagine the next situation: we need to highlight the block of cells in the pivot table that shows data about Canada and have this block highlighted no matter where Canada is placed - in rows or in columns. The other need might require highlighting the rows with Price to draw attention to them. Cell data object has info about its semantics thanks to properties measure, rows and columns.

By default, this info is not added to the cell builder, but it can be added inside customizeCell function. Our suggestion is to add it as attributes to the cell builder using attr parameter. If you add semantics of the cell to its HTML representation, you would be able to write CSS selectors based on the attributes.

Let’s look closer at several samples in this case.

4.a. Highlighting data about Canada no matter where Country is placed: in rows or columns

The idea is to add attributes hierarchy="Country" and member="Canada" to all the cells that display info about Canada.

For this customizeCell function should be the following:

function customizeCellFunction(cell, data) {
  if (data.rows) {
    for (var i = 0; i < data.rows.length; i++) {
      if (data.rows[i]["hierarchyCaption"] == "Country" && data.rows[i]["caption"] == "Canada") {
        cell.attr["hierarchy"] = data.rows[i]["hierarchyCaption"];
        cell.attr["member"] = data.rows[i]["caption"];
      }
    }
  }

  if (data.columns) {
    for (var i = 0; i < data.columns.length; i++) {
      if (data.columns[i]["hierarchyCaption"] == "Country" && data.columns[i]["caption"] == "Canada") {
        cell.attr["hierarchy"] = data.columns[i]["hierarchyCaption"];
        cell.attr["member"] = data.columns[i]["caption"];
      }
    }
  }
}

Then, after attributes were added, the following CSS selector can be written:

#fm-pivot-view #fm-grid-view div[hierarchy="Country"][member="Canada"] {
  background-color: #CCCCCC;
}

And all the cells on the grid that have hierarchy="Country" and member="Canada" attributes will be highlighted with #CCCCCC color.

Live sample: JSFiddle - Highlighting Country Canada on any place in rows or columns

You can try changing the position of Country hierarchy in rows, put it in columns, expand Canada, apply sorting to the grid - Canada block will remain highlighted.

4.b. Highlighting the rows with Price

This sample is similar to the previous one, but the information about measure will be added to the cells inside customizeCell function, as follows:

function customizeCellFunction(cell, data) {
  if (data.measure) {
    cell.attr["measure"] = data.measure.name;
  }
}

Each HTML cell will have measure attribute and the following CSS selector will highlight the rows with Price:

#fm-pivot-view #fm-grid-view div[measure="Price"] {
  background-color: #B2DBBF;
}

Live sample: JSFiddle - Highlighting rows with measure Price

4.c. Adding all the semantic info to cell builder attributes

Also, you can add all the semantic info to cell builder attributes the following way:
JSFiddle - Highlighting cells based on its semantic

This sample takes into account the position of the hierarchies in rows and in columns.

Case 5. Customizing cells based on conditional formatting

One of our customers wanted to highlight the entire row in the pivot table if the condition of the conditional formatting is true for at least one cell in this row. customizeCell allows quick implementation of this feature.

Cell data object contains a list of the conditional formatting ids that are true for this cell. This list is in the cell object property conditions.

Check the example that applies formatting to the entire row if the condition is true for at least one cell: JSFiddle - Customizing cells based on the conditional formatting.

customizeCell function in this sample composes CSS styles for the rows that should be highlighted. Only cell data object is used for this, cell builder is not used in this sample at all. Also, events aftergriddraw and beforegriddraw are used to add styles to DOM and to remove previously added styles respectively.

This sample demonstrates rather advanced API usage, but the code is self-explanatory.

Case 6. Representing numbers by icons

Let us draw your attention to our cell renderer demo where cell values are replaced with the images depending on to which interval the value belongs: high, middle, etc. This demo is also based on customizeCell hook.

Here is a live sample: JSFiddle - Cell renderer demo

Please inspect the code of the live sample and you will see that inside customizeCell function the following cell data object parameters are used: type and value. You are already familiar with type property and when it is "value" this means that the cell belongs to the numeric body of the table. The property value contains this numeric cell value and depending on this property the entire cell builder text is replaced by the corresponding <img> tag.

This case describes adding links to all the countries in the report to show additional details for each of them. customizeCell function wraps a country name with <a> link that points to the respective Wikipedia article.

Simple HTML content of the cell that was available in customizeCell function in 2.3 version was replaced with the cell builder in 2.4 version of the component. The property text of the cell builder contains the text of the cell which may also contain HTML, e.g. icons for expand, collapse, drill up and down, sorting, etc. When we want to add a hyperlink to such a cell with icons, we need to take them into account. The updated sample JSFiddle - Add hyperlinks illustrates how you can manipulate cell.text to add <a> tag inside and keep icons there.

The possibilities of customizeCell are not limited by the above 7 cases. This API call covers much more variants of visualization. Hopefully, this guide will inspire you to style, display, and emphasize your data in your own way.

API documentation:

Subscribe to our news: