Problem/Motivation

There is no hook to alter individual tab content after the tab type plugin renders it. The only way to modify rendered tab output is to write a custom tab renderer.

A simple alter hook would allow modules to modify tab content without subclassing the renderer.

Proposed resolution

Add a hook_quicktabs_tab_content_alter() that fires after $object->render($tab) in both the server-rendered path (QuickTabs::render()) and the AJAX
controller (QuickTabsController::ajaxContent()):

$render = $object->render($tab);                                                                                                                                                        
  $this->moduleHandler->alter('quicktabs_tab_content', $render, $tab, $instance);

API changes

New hook: hook_quicktabs_tab_content_alter(array &$render, array $tab, QuickTabsInstance $instance).

Issue fork quicktabs-3606679

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

loze created an issue. See original summary.

loze’s picture

Issue summary: View changes

loze’s picture

Status: Active » Needs review

Added the new hook.

Once #3606674: hook_quicktabs_instance_alter() not invoked on AJAX tab loads is merged, we can add test coverage for this hook using the same quicktabs_alter_test module introduced there. The test would add a hook_quicktabs_tab_content_alter() implementation
and verify it fires on all three render paths: the default tab in AJAX mode, all tabs in non-AJAX mode, and the AJAX controller for lazily loaded tabs.

joelpittet’s picture

Thanks for the proposed hook, sounds like a d7 feature that didn’t get ported

What is the use case for this?

Every feature comes at a cost of complexity, good to weigh it.

loze’s picture

Thanks for taking a look.

My use case was adding contextual links to Views-based tabs. Views blocks and pages get the "edit view" pencil natively, but that gets lost when rendered through QuickTabs.

In digging into this though, I found that the initial/default tab actually already has contextual links without the hook, the View render array goes through the normal pipeline and contextual_preprocess() picks up #contextual_links just fine. The problem is only with secondary tabs loaded via AJAX.

In 4.2.1, ViewContent::doRender() pre-renders AJAX tabs with renderRoot() and returns #markup. By the time the alter hook fires, the render array is already flat HTML, so any #contextual_links added by the hook never reach contextual_preprocess(). In 4.1.0 this worked because buildRenderable() was returned as-is for all tabs.

So I think the real fix is adding #contextual_links inside ViewContent::doRender() itself, after $view->buildRenderable() but before the renderRoot() call. That way they're part of the render array when it gets flattened and they survive the AJAX path. I'll open a separate MR for that.

Given all that, the hook probably isn't necessary, at least not for my use case. If you don't see value in keeping it as a general extension point, I understand pulling it.

loze’s picture

So, I ended up opening a new issue #3606793: Views tabs missing contextual links on AJAX-loaded tabs

If we do that that I don't need this alter hook.

joelpittet’s picture

I am way more comfortable baking that contextual links in, but we can leave this open if there are some strong case/support for the extension point!

Thanks for the details for why you’re looking for this!