Cms: Filtering and other parameters not working for nav

Created on 24 Aug 2020  路  8Comments  路  Source: statamic/cms

Bug Description

I can鈥檛 get filtering as well as limit/offset to work for the nav tag.

How to Reproduce

{{ nav:collection:pages max_depth="2" scope="tag" is_hidden:isnt="true" limit="3" }} is an approximation of a nav tag I used in v2. It pulls all pages, whether they have is_hidden set or not, and does not stop at 3, nor does an offset work.

Is this the result of this ominous comment, that this wasn鈥檛 fixed before release? If so, how do I make this happen? https://github.com/statamic/cms/issues/967#issuecomment-600116174

Environment

Statamic 3.0.0 Pro
Laravel 7.25.0
PHP 7.3.17
statamic/migrator dev-master

  • Fresh install from statamic/statamic (then imported from v2)
v2 compatibility

Most helpful comment

Ah yeah sorry, I didn't actually have the is_hidden field in my blueprint. Updated the snippet for you.

All 8 comments

Here鈥檚 the entire section in question from my nav partial.

{{ nav:collection:pages max_depth="2" scope="tag" is_hidden:isnt="true" limit="3" }}
<li class="nav-item {{ if is_current or is_parent }} active {{ /if }} {{ if children || slug == 'use-cases' }} dropdown {{ /if }} ">
    {{ if children }}
        <a  class="nav-link dropdown-toggle"
            href="{{ url }}"
            id="navbarDropdown"
            aria-haspopup="true"
            aria-expanded="false">
            {{ tag:nav_title or title }}
        </a>
        <div class="dropdown-menu">
            {{ if url == '/product' }}
                <a class="dropdown-item{{ if is_current }} active{{ /if }}" href="{{ url }}">{{ long_title }}</a>
            {{ else }}
                <a class="dropdown-item{{ if is_current }} active{{ /if }}" href="{{ url }}">Overview</a>
            {{ /if }}
            {{ children scope="tag" }}
                <a class="dropdown-item{{ if is_current }} active{{ /if }}" href="{{ url }}">{{ tag:nav_title or title }}</a>
            {{ /children }}
        </div>
    {{ elseif slug == 'use-cases' }}
        <a  class="nav-link dropdown-toggle"
            href="{{ url }}"
            id="navbarDropdown"
            aria-haspopup="true"
            aria-expanded="false">
            {{ tag:nav_title or title }}
        </a>
        <div class="dropdown-menu">
            <a class="dropdown-item{{ if is_current }} active{{ /if }}" href="{{ url }}">Overview</a>
            {{ collection from="use-cases" limit="3" scope="entry" }}
                <a class="dropdown-item{{ if segment_2 == entry:slug }} active{{ /if }}" href="{{ url }}">{{ title }}</a>
            {{ /collection }}
                <a class="dropdown-item{{ if segment_1 == 'use-cases' && ! segment_2 }} active{{ /if }}" href="{{ url }}">View All</a>
                <a class="dropdown-item external" href="https://seamster.io">Seamster</a>
        </div>
    {{ else }}
    <a class="nav-link {{ if is_current or is_parent }}active{{ /if }}" href="{{ url }}">{{ title }}</a>
    {{ /if }}
</li>
{{ /nav:collection:pages }}

Running into this same issue migrating a site from v2 > v3. Navigations are great for certain things, but the ability to get all pages except for those hidden by a yaml field is so handy.

I ran into this again on a new site I鈥檓 migrating that has a complicated enough nav that I REALLY don鈥檛 want to have to go through and build a separate nav, nor do I want to require the client to have to add each page to a separate nav setup every time they add a new page.

This is really becoming a thorn in my side. :-)

Usually there's a way to write a little custom PHP and do the thing that doesn't exist, until it exists.

Here's a tag for you to use in the mean time. Pop it in app/Tags/NavExcludingHidden.php

<ul>
{{ nav_excluding_hidden include_home="true" }}
    <li>
        {{ title }}
        {{ if children }}
            <ul>{{ *recursive children* }}</ul>
        {{ /if }}
    </li>
{{ /nav_excluding_hidden }}
</ul>
<?php

namespace App\Tags;

use Statamic\Fields\Value;
use Statamic\Support\Arr;
use Statamic\Tags\Nav;

class NavExcludingHidden extends Nav
{
    public function index()
    {
        return $this->filterOutHidden(parent::index());
    }

    private function filterOutHidden($pages)
    {
        return collect($pages)->reject(function ($page) {
            $hidden = Arr::get($page, 'is_hidden');
            return $hidden instanceof Value ? $hidden->value() : $hidden;
        })->map(function ($page) {
            $page['children'] = $this->filterOutHidden($page['children']);
            return $page;
        })->all();
    }
}

Rock on. Thanks.

Well, so far, that filters out everything except Home. I'll see if I can figure it out from here, though.

Ah yeah sorry, I didn't actually have the is_hidden field in my blueprint. Updated the snippet for you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wm-simon picture wm-simon  路  3Comments

riasvdv picture riasvdv  路  4Comments

robdekort picture robdekort  路  3Comments

aerni picture aerni  路  4Comments

aerni picture aerni  路  3Comments