Заметки / Joomla 4 - How to build collapsible menu from article categories

Ethicist 18 января 2022
Collapsible menu from Article Categories in Joomla 4
Collapsible menu from Article Categories in Joomla 4

Markup

<?php
    defined('_JEXEC') or die;
    
    use Joomla\CMS\Factory;
    use Joomla\CMS\Router\Route;

    /* ... */
?>
<aside>
    <ul class="list-unstyled ps-0">
        <?php
            $db = Factory::getContainer()->get('DatabaseDriver');
            $query = $db->getQuery(true);
            
            $query->select("`id`, `title`, `parent_id`, `alias`");
            $query->from($db->quoteName("#__categories"));
            $query->where($db->quoteName("extension") . ' LIKE "com_content"');
            $query->order($db->quoteName("lft") . " ASC");
            
            $db->setQuery($query);
            $results = $db->loadObjectList();
            
            $categories = [];
            
            $root_category_id = 9; # set your own root category ID
            
            if (count($results)) {
                $temp_options = [];
            
                foreach ($results as $item) {
                    array_push($temp_options, [
                        "catid" => $item->id,
                        "title" => $item->title,
                        "parent_id" => $item->parent_id,
                        "alias" => $item->alias,
                    ]);
                }
            
                $parent_categories = [];
                $child_categories = [];
            
                foreach ($temp_options as $option) {
                    if ($option["parent_id"] == $root_category_id) {
                        $parent_categories[] = [
                            "catid" => $option["catid"],
                            "title" => $option["title"],
                            "alias" => $option["alias"],
                            "route" => Route::_(ContentHelperRoute::getCategoryRoute($option["catid"]))
                        ];
                    } else {
                        $catid_match = array_search(
                            $option["parent_id"],
                            array_column($parent_categories, "catid")
                        );
            
                        if ($catid_match) {
                            $child_categories[$option["parent_id"]][] = [
                                "catid" => $option["catid"],
                                "title" => $option["title"],
                                "alias" => $option["alias"],
                                "route" => Route::_(ContentHelperRoute::getCategoryRoute($option["catid"]))
                            ];
                        }
                    }
                }
                
                foreach($parent_categories as $p_cat) {
                    if(count($child_categories[$p_cat["catid"]]) > 0) {
                        /* parent category + toggler */
                        
                        echo '<li class="mb-1">';
                        
                        echo '<a' .
                            ' class="btn d-flex w-100 btn-toggle align-items-center collapsed p-3"' .
                            ' data-bs-toggle="collapse"' .
                            ' data-bs-target="#catalog-collapse-'.$p_cat['catid'].'"' .
                            ' aria-expanded="false"' .
                            ' href="javascript:;"' .
                            '>' .
                            $p_cat["title"] .
                            ' </a>';
                            
                        echo '<div class="collapse" id="catalog-collapse-'.$p_cat['catid'].'">'.
                            '<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">';
            
                        foreach($child_categories[$p_cat["catid"]] as $c_cat) {
                            echo '<li><a href="'.$c_cat["route"].'" class="btn d-flex w-100 align-items-center rounded collapsed p-3 m-0">' .
                            $c_cat['title'] .'</a></li>';
                        }
                        
                        echo '</ul></div></li>';
                        
                    } else {
                        echo '<li class="mb-1"><a class="btn d-flex w-100 align-items-center collapsed p-3 m-0" href="'.$p_cat["route"].'">'.
                        $p_cat["title"] . '</a></li>';
                    }
                }
            }
        ?>
    </ul>
</aside>

Additonal styling for Bootstrap

.dropdown-toggle {
    outline: 0;
}

.nav-flush .nav-link {
    border-radius: 0;
}

.btn-toggle {
    display: inline-flex;
    align-items: center;
    padding: 0.25rem 0.5rem;
    font-weight: 600;
    color: rgba(0, 0, 0, 0.65);
    background-color: transparent;
    border: 0;
}

.btn-toggle:hover,
.btn-toggle:focus {
    color: rgba(0, 0, 0, 0.85);
    background-color: #f5f5f5;
}

.btn-toggle::before {
    width: 1.25em;
    line-height: 0;
    content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%280,0,0,.5%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e");
    transition: transform 0.35s ease !important;
    transform-origin: 0.5em 50% !important;
}

.btn-toggle[aria-expanded="true"] {
    color: rgba(0, 0, 0, 0.85) !important;
}

.btn-toggle[aria-expanded="true"]::before {
    transform: rotate(90deg) !important;
}

.btn-toggle-nav a {
    display: inline-flex;
    padding: 0.1875rem 0.5rem;
    margin-top: 0.125rem;
    margin-left: 1.25rem;
    text-decoration: none;
}

.btn-toggle-nav a:hover,
.btn-toggle-nav a:focus {
    background-color: #f5f5f5;
}

Смотрите также: