• Your Files, Your Rules – Upgrade Today! Exciting news! With our new ownership, you’re no longer limited—upload files from here to any website without getting Banned. 🚀 Why wait? Upgrade your account now
Tabbed Options

XF2 Tutorials Tabbed Options

XFdownloadStore

Virtual Assistant

Administrator
This guide will allow you to have a single option group for all your options, separating them into tabbed sections rather than forcing users to change option groups.

EXAMPLE:
Tabbed Options-1.webp



Tabbed Options-2.webp


Code Event Listener:
Event: templater_macro_pre_render
Event Hint: admin:option_macros:option_form_block
Execute Callback: Your\Namespace\Listener :: templaterMacroPreRender

PHP Code:
PHP:
<?php
namespace Your\Namespace;
class Listener
{
    public static function templaterMacroPreRender(\XF\Template\Templater $templater, &$type, &$template, &$name, array &$arguments, array &$globalVars)
    {
        if (!empty($arguments['group']) && $arguments['group']->group_id == 'your_group')
        {
            // Override template name
            $template = 'your_namespace_option_macros';
        
            // Or use 'option_form_block_tabs' for tabs
            $name = 'option_form_block';
        
            // Your block header configurations
            $arguments['headers'] = [
                'generalOptions'      => [
                    'label'           => \XF::phrase('general_options'),
                    'minDisplayOrder' => 0,
                    'maxDisplayOrder' => 2000,
                    'active'          => true // Only used for tabs, indicates default active tab
                ],
                'otherOptions'        => [
                    'label'           => \XF::phrase('other_options'),
                    'minDisplayOrder' => 2000,
                    'maxDisplayOrder' => 3000
                ],
                'evenMoreOptions'     => [
                    'label'           => \XF::phrase('even_more_options'),
                    'minDisplayOrder' => 3000,
                    'maxDisplayOrder' => -1 // This allows for any higher display order value
                ],
            ];
        }
    }
}

Admin Template:
Template Name: your_namespace_option_macros

Template Contents:
HTML:
<xf:macro name="option_form_block" arg-group="" arg-options="!" arg-containerBeforeHtml="" arg-headers="{{ [] }}">
    <xf:if is="$options is not empty">
        <xf:form action="{{ link('options/update') }}" ajax="true" class="block">
            {$containerBeforeHtml|raw}
            <div class="block-container">
            
                <xf:foreach loop="$headers" value="$header">
                    <xf:macro name="option_rows" arg-header="{$header.label}"
                              arg-group="{$group}" arg-options="{$options}"
                              arg-minDisplayOrder="{$header.minDisplayOrder}" arg-maxDisplayOrder="{$header.maxDisplayOrder}" />
                </xf:foreach>

                <xf:submitrow sticky="true" icon="save" />
            </div>
        </xf:form>
    </xf:if>
</xf:macro>

<xf:macro name="option_form_block_tabs" arg-group="" arg-options="!" arg-containerBeforeHtml="" arg-headers="{{ [] }}">
    <xf:if is="$options is not empty">
        <xf:form action="{{ link('options/update') }}" ajax="true" class="block">
            {$containerBeforeHtml|raw}
            <div class="block-container">
                <h2 class="block-tabHeader tabs" data-xf-init="tabs" role="tablist">
                    <xf:foreach loop="$headers" key="$key" value="$header">
                        <a class="tabs-tab{{ $header.active ? ' is-active' : '' }}" role="tab" tabindex="0" aria-controls="{$key}">{$header.label}</a>
                    </xf:foreach>
                </h2>
                <ul class="tabPanes">
                    <xf:foreach loop="$headers" key="$key" value="$header">
                        <li class="{{ $header.active ? 'is-active' : '' }}" role="tabpanel" id="{$key}">
                            <xf:macro name="option_rows"
                                      arg-group="{$group}" arg-options="{$options}"
                                      arg-minDisplayOrder="{$header.minDisplayOrder}" arg-maxDisplayOrder="{$header.maxDisplayOrder}" />
                        </li>
                    </xf:foreach>
                </ul>
                <xf:submitrow sticky="true" icon="save" />
            </div>
        </xf:form>
    </xf:if>
</xf:macro>

<xf:macro name="option_rows" arg-header="" arg-group="!" arg-options="!" arg-minDisplayOrder="{{ 0 }}" arg-maxDisplayOrder="!">
    <xf:set var="$hundred" value="0" />

    <xf:if is="$header">
        <h3 class="block-formSectionHeader">{$header}</h3>
    </xf:if>

    <div class="block-body">
        <xf:foreach loop="$options" value="$option">
            <xf:if is="{$option.Relations.{$group.group_id}.display_order} >= $minDisplayOrder AND ({$option.Relations.{$group.group_id}.display_order} < $maxDisplayOrder OR $maxDisplayOrder == -1)">
                <xf:if is="$group">
                    <xf:set var="$curHundred" value="{{ floor($option.Relations.{$group.group_id}.display_order / 100) }}" />
                    <xf:if is="{{ $curHundred > $hundred }}">
                        <xf:set var="$hundred" value="{$curHundred}" />
                        <hr class="formRowSep" />
                    </xf:if>
                </xf:if>

                <xf:macro template="option_macros" name="option_row"
                          arg-group="{$group}" arg-option="{$option}" />
            </xf:if>
        </xf:foreach>
    </div>
</xf:macro>

There are two macros in this template. Change the configuration in the event listener as required.

  • Replace all instances of your_group with the option group ID you used.
  • Replace all instances of Your\Namespace or your_namespace with the relevant namespace you use.
  • I chose to separate my options per 1000 display order, but you can edit the PHP code and do it however you like.
 
Similar threads Most view View more
Back
Top