Skip to content

Mapping Dynamic Table Data into a Table

This page explains how a BPS dynamic table response is transformed into a renderable table in the UI, including the case where turtahun is present.

Visual 1 — Table Structure Mapping

This visual shows how response dimensions are mapped into rows, columns, and cell values — without relying on a separate SVG asset.

RESPONSE DIMENSIONS
vervarvarturvartahunturtahundatacontent

Each table value is built from a combination of these dimensions.

COMPOSITE KEY
7315+31+0+99+0=7315310990

Example: Pinrang × Population × 1999

RENDERED TABLE SHAPE
Region199920002001
Pinrang308,669311,595312,473
vervar → rows
tahun → columns
datacontent → cell values
Highlighted cell: Pinrang × Population × 1999 = 308669
read from datacontent[7315310990]

Core Mapping

  • Rows come from vervar
  • Main columns come from tahun
  • Sub-columns can come from turvar
  • A deeper sub-column level can come from turtahun
  • Cell values are read from datacontent
  • Every value is looked up using a composite key:
text
{vervar}{var}{turvar}{tahun}{turtahun}

Example:

text
7315 + 31 + 0 + 99 + 0 = 7315310990

Then lookup:

text
datacontent[7315310990] = 308669

Visual 2 — Full Mapping including turtahun

The visual below shows four important header structure cases:

  • Case A: single turvar + single turtahun
  • Case B: multiple turvar + single turtahun
  • Case C: single turvar + multiple turtahun
  • Case D: multiple turvar + multiple turtahun
BPS API — JSON response → table mapping
How to decode the datacontent key and render a multi-level header table
vervar+var+turvar+tahun+turtahunconcat of val fields
Example (Pinrang / Kec A / 1999 / Feb):7315+31+1+99+2="7315311992"
⚠ Key length is variable — always build by lookup, never fixed-width split.

JSON Response (Case D — all dimensions)
"vervar": [ {"val": 7315, "label": "Pinrang" } ]
"var": [ { "val": 31, "label": "Jumlah Penduduk", "unit": "Jiwa" } ]
"turvar": [
{ "val": 1, "label": "Kec A" },
{ "val": 2, "label": "Kec B" }
]
"tahun": [
{ "val": 99, "label": "1999" },
{ "val": 100, "label": "2000" }
]
"turtahun": [
{ "val": 2, "label": "Februari" },
{ "val": 3, "label": "Maret" }
]
"datacontent": {
"7315311992":101,234,
"7315312992":98,441,
"7315311993":102,887,
"7315312993":99,103, ... 8 keys total
}
Header Row Rules
Row 1
tahun  — always shown
colspan = count(turtahun) × count(turvar)
Row 2
turtahun  — skip if only 1 value
colspan = count(turvar)
Row 3
turvar  — skip if only 1 value
colspan = 1  (leaf column)
Wilayah
rowspan
= total header rows rendered (1, 2, or 3)
Cases at a glance
Asingle turvar + single turtahun1 header row
Bmultiple turvar, single turtahun2 rows: tahun → turvar
Csingle turvar, multiple turtahun2 rows: tahun → turtahun
Dmultiple turvar + multiple turtahun3 rows: tahun → turtahun → turvar
Loop: vervar × var × tahun × turtahun × turvar
→ build key → lookup datacontent → cell value
CASE ASingle turvar + single turtahun — 1 header row
Wilayah19992000
Pinrang308,669311,595
↑ 1999 cell key:7315310990= "7315310990"
CASE BMultiple turvar, single turtahun — 2 header rows (tahun → turvar)
Wilayah19992000
Kec AKec BKec AKec B
Pinrang308,669295,421311,595300,112
↑ tahun colspan =count(turvar)=2
CASE CSingle turvar, multiple turtahun — 2 header rows (tahun → turtahun)
Wilayah19992000
FebruariMaretFebruariMaret
Pinrang101,234102,887103,991105,112
↑ tahun colspan =count(turtahun)=2
CASE DMultiple turvar + multiple turtahun — 3 header rows (tahun → turtahun → turvar)
Wilayah19992000
FebruariMaretFebruariMaret
Kec AKec BKec AKec BKec AKec BKec AKec B
Pinrang101,23498,441102,88799,103103,991100,234105,112101,876
↑ tahun colspan =count(turtahun)×count(turvar)=2 × 2 = 4
↑ turtahun colspan =count(turvar)=2
↑ turvar colspan = 1(leaf)
vervar
var
turvar
tahun
turtahun

Mental Model Rules

1. Rows

Always start with vervar.

text
each item in vervar = one main row

2. Columns

  • if turvar only has one meaningful value or is effectively absent → columns can just be tahun
  • if turvar has multiple meaningful values → columns become turvar × tahun

3. Extra turtahun hierarchy

If there is more than one turtahun, the column header needs one more level.

Practical rule:

  • tahun is always the top level
  • turtahun becomes the middle level when count > 1
  • turvar becomes the lower level when count > 1

So the header structure can become:

text
tahun

or:

text
tahun -> turvar

or:

text
tahun -> turtahun

or in the full case:

text
tahun -> turtahun -> turvar

In stadata-js

Option 1 — toStructuredData()

Use this when you want full control over rendering the table.

typescript
const structured = table.toStructuredData()

Option 2 — DynamicTableHtmlGenerator

Use this when you want a quick HTML table.

typescript
import { DynamicTableHtmlGenerator } from 'stadata-js'

const html = DynamicTableHtmlGenerator.generate(table)

When do you need manual parsing?

Manual parsing is usually only needed when:

  • you want a highly custom visualization
  • you want to export to your own custom format
  • you want pivot logic different from the built-in helpers

Otherwise, prefer the built-in helpers.

See Also

Released under the MIT License.