The embed-and-customize sprint, seven features in seven versions
A two-week run that landed the Gutenberg block, the Elementor widget, merged-table views across multiple Gravity Forms, scoped per-table typography, dynamic placeholder tokens, container-fit table width, and per-column shortcode rendering. The "drop a Gravity Table anywhere and make it match the site" wave.
- v4.1.60, native `gravity-tables/table` Gutenberg block, no more shortcode strings, full server-rendered preview in the editor
- v4.1.61, Elementor widget registered through `elementor/widgets/register` with sidebar controls
- v4.1.62, merged-table combined view, aggregate rows from multiple source Gravity Tables, edits route back to the correct underlying form
- v4.1.64, per-table typography, Google Fonts, scoped CSS, `font-display: swap`
- v4.1.66, per-column render-shortcodes, `do_shortcode()` on cell content, opt-in per column so existing tables stay zero-overhead
The fastest way to get a Gravity Table on a page used to be: paste the shortcode into a Code or Shortcode block, save, reload. That worked, but it left a UX gap, every other content type in modern WordPress is a block or a builder widget, with a live preview in the editor. Why not us?
This release run closes that gap and adds five more “make it fit your site exactly” knobs. Seven versions, two weeks, one coherent theme: embedding and customization.
v4.1.60, Native Gutenberg block#
gravity-tables/table is a real first-class WordPress block. Drop it from the inserter, pick a table from the sidebar dropdown, see the live preview right there in the editor.
The block is registered via register_block_type() with a server-side render_callback, meaning the editor preview is the same HTML the frontend gets. There is no separate “approximation” rendered in the block editor that diverges from production. What you see in Gutenberg is what your visitors see.
Inspector sidebar controls cover:
- Table id (dropdown of all configured tables)
- Show / hide search, filters, pagination, export buttons
- Default sort column + direction
- Page size override
Anything more exotic still works through the shortcode form (the block edits live alongside the original shortcode-in-block flow if you prefer that). The block is purely additive.
v4.1.61, Elementor widget#
Same idea, Elementor flavor. GT_Elementor_Widget extends \Elementor\Widget_Base, registered conditionally on elementor/widgets/register only when Elementor is active (gated by did_action('elementor/loaded')).
Sidebar controls match the Gutenberg block parity-for-parity:
- Table id
- Show / hide search, filters, pagination, export
- Entries-per-page override
The render() method delegates to do_shortcode('[gravity_table id="X" ...]'), guaranteeing output parity between the widget and the shortcode. You can swap one for the other freely.
v4.1.62, Merged-table combined view#
Sometimes the data you want in one table actually lives across two or three Gravity Forms. A “leads” form, a “demo requests” form, a “support inquiries” form, all going to the same sales team, all wanting the same dashboard.
The GT_Merged_Table class aggregates entries from multiple source Gravity Tables into a single rendered view. Each row is stamped with _source_table_id so the UI knows which underlying form to route inline edits back to. get_total_count() returns the combined row count for pagination.
The shortcode renderer checks for type === 'merged' in the table config and delegates to GT_Merged_Table instead of the default entry repository. From the visitor’s perspective, it’s one table; under the hood, edits route to the correct form, validation runs against the correct field schema, and the audit log records the right form id alongside the entry id.
v4.1.63, Dynamic placeholder tokens#
Six tokens you can drop into a cell’s default_value or header field, resolved server-side at render time:
{current_date},{current_time},{current_datetime}, using the site’s WP timezone (wp_timezone()) and configured date/time formats{current_user}, display name of the logged-in user{site_name},{site_url}
The GT_Placeholder_Service class handles resolution. Tokens are expanded before output, so the rendered HTML and any export (CSV, Excel, PDF) sees the resolved value, not the literal {token} string.
The most common use: a “Reported on” column that defaults to today’s date, or a header that says {site_name} customer dashboard without you having to bake the site name into every shortcode.
v4.1.64, Per-table typography#
Until now, table styling came from the host theme + the plugin’s CSS variables. That’s fine for most sites; for sites with brand-specific typography it left a gap.
The new GT_Typography_Service accepts a typography config in the table settings:
typography:
font_family: 'Inter'
header_font_size: '0.875rem'
header_font_weight: '600'
header_color: '#0f172a'
body_font_size: '0.95rem'
body_font_weight: '400'
body_color: '#1e293b'
line_height: '1.6'
Three properties of the implementation worth calling out:
- Scoped CSS, not global. The generated CSS is scoped to the specific table’s instance selector. Different tables on the same page can have different typography; nothing bleeds.
- Google Fonts handled cleanly. When
font_familyis a Google Font,maybe_enqueue_google_font()enqueues it throughwp_enqueue_style()withfont-display: swap. No FOUT, no third-party loader, no extra JS. - Default-when-empty. When the typography config is empty (the default for upgraded installs), nothing changes. Existing tables continue to use the host-theme typography exactly as before.
v4.1.65, Container-fit width#
A new table_width setting reads from the shortcode renderer and passes through to the template wrapper as $gt_table_width. Three accepted shapes:
auto, table sizes itself to its content100%, fills the container (the prior default behaviour)800px(or any CSS dimension), explicit width
class-gt-admin.php sanitizes and persists the value alongside the rest of the table settings. When absent or empty, behaviour is exactly what it used to be, full-width within the surrounding layout, so upgraded installs see no change.
The new mode this enables: tables that need to sit side-by-side with other content (a sidebar metric, a hero image), or that explicitly should not stretch on extremely wide containers.
v4.1.66, Per-column render-shortcodes#
A column can now opt into having its cell values passed through do_shortcode() before output, by setting render_shortcodes: true in its field_configurations entry.
Why opt-in per column? Two reasons:
- Performance.
do_shortcode()is not free, it has to scan every cell value for shortcode patterns. On tables with thousands of cells, you don’t want that overhead on columns that will never contain shortcodes. - Safety. Shortcode rendering is essentially “execute this string as PHP”. You only want it on columns where the content is admin-controlled (calculated fields, saved templates), not arbitrary user input.
The flag works in both server-side render (class-gt-shortcode.php) and AJAX-loaded rows (class-gt-ajax.php). Columns without the flag are unaffected, zero overhead, zero behavioural change.
The most-asked use case: a “View entry” column where the cell value is something like [gravityview_entry_link entry_id="{entry_id}" view_id="42"]Open[/gravityview_entry_link], rendering as a real link to a GravityView detail page.
What this means in aggregate#
Take the 4.1.60-4.1.66 line as a whole, and the answer to “where can I put a Gravity Table?” becomes:
- Gutenberg post / page: insert the block
- Elementor design: drop the widget
- Bricks / Divi / Beaver / Oxygen / Breakdance: shortcode element (unchanged, still works)
- Multiple forms feeding one table: merged-table type
- Tight design system: per-table typography + container-fit width
- Cells with shortcodes / dynamic content: render-shortcodes flag + placeholder tokens
The plugin meets your build wherever it is, instead of forcing you to meet the plugin.
Upgrade path#
Upgrade from any 4.1.x is safe and additive. No setting changes required. The new features are off by default, existing tables behave exactly as they did pre-upgrade. To use a new feature, opt in via the Gutenberg block / Elementor widget / table settings UI, or add the relevant config key to your field_configurations for per-column features.
Related#
- Integrations, the full compatibility matrix, now updated to reflect the native block + widget
- Shortcode reference,
table_width, typography, placeholder tokens documented - Roadmap, what’s next in 4.3