Ticket

MLE-299

https://snai.pe/posts/rendering-tables

Introduction

The shape Table of package pamela by revodigital allows drawing a table in a pamela stage. It has been created the same way as Barcode and allows you to perform several operations, like:

  • Represent a series of rows and columns

  • Format each row’s or column’s text

  • Handle automatic size calculating

  • Represent each cell with custom advanced configuration

  • Merge cells and create complex tables

  • Handle dynamic size and scaling

Creating

Adding a Table to a stage can be achieved using its constructor:

constructor(options: TableConfig) {...}
TYPESCRIPT

Configuration

Constructor receives the following object as configuration:

export interface TableConfig extends ShapeConfig {
  cells?: Matrix2D<CellConfig>;
}
TYPESCRIPT

The Pamela.Table shape is very simple. It receives a Matrix2D containing all the cells to render. How is each cell configured?

Cell configuration and capabilities

The configuration for each cell is held by the interface CellConfig. These are its properties:

export interface CellConfig extends ITextConfiguration {
  /**
   * Cell content (data to display using text configuration)
   */
  content?: string;
  
  /**
   * Cell background color
   */
  fill?: string;

  /**
   * Cell visibility modifier (if set to false it will be hidden)
   */
  visible?: boolean;

  /**
   * Left border configuration
   */
  leftBorder?: BorderConfig;

  /**
   * Right border configuration
   */
  rightBorder?: BorderConfig;

  /**
   * Bottom border configuration
   */
  bottomBorder?: BorderConfig;

  /**
   * Top border configuration
   */
  topBorder?: BorderConfig;

  /**
   * Cell width in percentage
   */
  width?: number;

  /**
   * Cell height in percentage
   */
  height?: number;

  /**
   * Only for storage purposes: if this cell with auto width?
   */
  autoWidth?: boolean;

  /**
   * Only for storage purposes: if this cell with auto height?
   */
  autoHeight?: boolean;
}
TYPESCRIPT

As you can see, each Cell of the table has a lot of possible configurations. Main configurations are:

  • Specific border configuration

  • Content value

  • Content format configuration (using TextConfiguration)

  • Cell sizing mode

  • Padding

  • Font configuration

  • Alignment (vertical and horizontal)

  • Fill color

  • And many more…

Each cell of a Pamela.Table can have a different configuration. Of corse there are some rules to follow:

  • Every percentage (width or height) should be valid

  • The sum of all the width of cells into a row should be 100%

  • The sum of all the height of cells into a column should be 100%

If you don’t respect this rules, drawing the table could lead to graphic inconsistencies.

How can i build and edit my tables?

As we have seen, Pamela.Table only cares about rendering a Matrix2D of CellConfig instances. It does not expose any api to edit its content. It is meant to be a read-only object. This means that once we have created a table, we shouldn’t modify its content. This is for optimization purposes.

Does this mean that i can’t modify a Table? No. There is a very advanced way of doing this.

The table builder

Table editing is possible and recommended using TableBuilder. It’s a specific class that cares about all the possible actions to edit a Table. Since it is a builder, it has a build method that returns a Pamela.Table instance. Every action will be performed on the builder object and that will be stored into the Table.

const tBuilder = new TableBuilder({<initial>});

// Actions to create my table (add a row, set the color, etc...)
const table: Pamela.Table = tBuilder.build()

layer.add(table);
TYPESCRIPT

This is the general snippet to construct a new table using a TableBuilder class.

Editing an existing table

The process described by the previous steps is very good for creating new tables. What if i want to edit an existing table? Is it possible or should i create a new one?

Yes, you can edit an existing table. Each Pamela.Table has a method toBuilder that simplifies the creation of a TableBuilder to edit the selected table.

const tBuilder = table.toBuilder();

tBuilder.addColumn({
...
})

tBuilder.buildTo(table);
TYPESCRIPT

Using this snippet, we will be able to perform some operations on the already existing cells of our table and override the existing one. This is recommended only for little operations.

Each builder should always create a new table, but it is allowed to edit existing ones