Search code examples
typo3typoscriptfluid

Why my DataProcessing\MenuProcessor don't show level-3 and level-4 for my page tree


I use Bootstrap_package v10 and Typo3 9, the menu processor doesn't show the level-3 and 4 for my pagetree.

I'm using the original templates from bootstrap package, the code is below:

10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
10 {
    levels = 5
    special = directory
    special.value = 26969
    expandAll = 1
    includeSpacer = 1
    as = mainnavigation
    dataProcessing {
        10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor
        10 {
            references.fieldName = nav_icon
            as = icon
            if {
                isTrue.stdWrap.cObject = COA
                isTrue.stdWrap.cObject {
                    10 = TEXT
                    10.value = 1
                    10.if.isTrue = {$page.theme.navigation.icon.enable}
                    20 = TEXT
                    20.value = 1
                    20.if.isTrue = {$page.theme.navigation.dropdown.icon.enable}
                }
            }
        }
    }
}

and this is the fluid code :

<f:section name="MainNavigation">
    <f:if condition="{menu}">
        <ul class="navbar-nav">
            <f:for each="{menu}" as="item">
                <f:if condition="{item.spacer}">
                    <f:then>
                        </ul>
                        <ul class="navbar-nav">
                    </f:then>
                    <f:else>
                        <li class="nav-item{f:if(condition: item.active, then:' active')}{f:if(condition: item.children, then:' dropdown dropdown-hover')}">
                            <a href="{item.link}" id="nav-item-{item.data.uid}" class="nav-link{f:if(condition: item.children, then:' dropdown-toggle')}"{f:if(condition: item.target, then: ' target="{item.target}"')} title="{item.title}"{f:if(condition: item.children, then:' aria-haspopup="true" aria-expanded="false"')}>
                                <f:if condition="{theme.navigation.icon.enable} && {item.icon}">
                                    <span class="nav-link-icon">
                                        <f:if condition="{item.icon.0.extension} === svg">
                                            <f:then>
                                                <bk2k:inlineSvg image="{item.icon.0}" width="{theme.navigation.icon.width}" height="{theme.navigation.icon.height}" />
                                            </f:then>
                                            <f:else>
                                                <f:image image="{item.icon.0}" alt="{item.icon.0.alternative}" title="{item.icon.0.title}" width="{theme.navigation.icon.width}" height="{theme.navigation.icon.height}" />
                                            </f:else>
                                        </f:if>
                                    </span>
                                </f:if>
                                <span class="nav-link-text">{item.title}<f:if condition="{item.current}"> <span class="sr-only">(current)</span></f:if></span>
                            </a>
                            <f:if condition="{item.children}">
                                <ul class="dropdown-menu" aria-labelledby="nav-item-{item.data.uid}">
                                    <f:for each="{item.children}" as="child">
                                        <f:if condition="{child.spacer}">
                                            <f:then>
                                                <li class="dropdown-divider"></li>
                                            </f:then>
                                            <f:else>
                                                <li>
                                                    <a href="{child.link}" class="dropdown-item{f:if(condition: child.active, then:' active')}"{f:if(condition: child.target, then: ' target="{child.target}"')} title="{child.title}">
                                                        <f:if condition="{theme.navigation.dropdown.icon.enable} && {child.icon}">
                                                            <span class="dropdown-icon">
                                                                <f:if condition="{child.icon.0.extension} === svg">
                                                                    <f:then>
                                                                        <bk2k:inlineSvg image="{child.icon.0}" width="{theme.navigation.dropdown.icon.width}" height="{theme.navigation.dropdown.icon.height}" />
                                                                    </f:then>
                                                                    <f:else>
                                                                        <f:image image="{child.icon.0}" alt="{child.icon.0.alternative}" title="{child.icon.0.title}" width="{theme.navigation.dropdown.icon.width}" height="{theme.navigation.dropdown.icon.height}" />
                                                                    </f:else>
                                                                </f:if>
                                                            </span>
                                                        </f:if>
                                                        <span class="dropdown-text">{child.title}<f:if condition="{child.current}"> <span class="sr-only">(current)</span></f:if></span>
                                                    </a>
                                                </li>
                                            </f:else>
                                        </f:if>
                                    </f:for>
                                </ul>
                            </f:if>
                        </li>
                    </f:else>
                </f:if>
            </f:for>
        </ul>
    </f:if>
</f:section>

The fluid is calling a page child but i don't know if it is recursive or not so it can showa all levels, what am I missing there, it seems like i'm the first one that having this issue ?

Thanks in advance for any help.


Solution

  • First you should verify if the data is available for more than the first two levels:
    insert a <f:debug title="mainnavigation">{mainnavigation}</f:debug> in your template.

    Then inspect your templates whether they are ready to display more than two levels.
    I can imagine your templates show the first level, for second level a partial is called, but that partial does not call itself if necessary.
    Except if you need some level specific markup (e.g. 'class="level1") you can build up menus by stacking the levels inside each other (giving stacked uls). So you either have a recursive call with stacked menus of the same markup or you define a partial for each level with individual markup (or you define a variable which contains the current level and call the partial recursive).


    it's even worse: both levels are written out in the same template file, no partial (or section) is used.

    I would change it to:
    (I stayed with one file and instead of an additional partials I call a section, which can be in the same file)

    <f:section name="MainNavigation">
        <f:if condition="{menu}">
            <ul class="navbar-nav">
                <f:for each="{menu}" as="item">
                    <f:render section="subLevel" arguments="{item:item}" />
                </f:for>
            </ul>
        </f:if>
    </f:section>
    
    <f:section name="subLevel">
        <f:if condition="{item.spacer}">
             <f:then>
                 <li class="dropdown-divider"></li>
             </f:then>
             <f:else>
                 <li class="nav-item{f:if(condition: item.active, then:' active')}{f:if(condition: item.children, then:' dropdown dropdown-hover')}">
                     <a href="{item.link}" id="nav-item-{item.data.uid}" class="nav-link{f:if(condition: item.children, then:' dropdown-toggle')}"{f:if(condition: item.target, then: ' target="{item.target}"')} title="{item.title}"{f:if(condition: item.children, then:' aria-haspopup="true" aria-expanded="false"')}>
                     <f:if condition="{theme.navigation.icon.enable} && {item.icon}">
                          <span class="nav-link-icon">
                              <f:if condition="{item.icon.0.extension} === svg">
                                  <f:then>
                                      <bk2k:inlineSvg image="{item.icon.0}" width="{theme.navigation.icon.width}" height="{theme.navigation.icon.height}" />
                                  </f:then>
                                  <f:else>
                                      <f:image image="{item.icon.0}" alt="{item.icon.0.alternative}" title="{item.icon.0.title}" width="{theme.navigation.icon.width}" height="{theme.navigation.icon.height}" />
                                  </f:else>
                              </f:if>
                          </span>
                      </f:if>
                      <span class="nav-link-text">{item.title}<f:if condition="{item.current}"> <span class="sr-only">(current)</span></f:if></span>
                     </a>
                     <f:if condition="{item.children}">
                         <ul class="dropdown-menu" aria-labelledby="nav-item-{item.data.uid}"> 
                             <f:for each="{item.children}" as="child">
                                 <f:render section="subLevel" arguments="{item:child}" />
                             </for>
                         </ul>
                    </f:if>
                </li>
            </f:else>
        </f:if>
    </f:section>
    

    Notice the changed markup for spacer in the first level!
    Further changes might occur as I have not compared the code but concentrated on building up clean markup.


    Increasing a 'parameter' for the recursion.

    for an increasing value (level1, level2, level3...) you need a viewhelper in TYPO3 prior version 9:
    this viewhelper can be realised in typoscript:

    lib.math = TEXT
    lib.math {
      current = 1
      prioriCalc = 1
    }
    

    then you can change the initial call to the SubLevel section to:

    <f:render section="subLevel" arguments="{item:item,level:1}" />
    

    Now you have a fluid variable level with the value 1.

    the recursive call must be changed to:

    <f:render section="subLevel" arguments="{item:child,level:{f:cObject(typoscriptObjectPath:'lib.math', data:'{level}+1')}}" />
    

    for increasing values 2, 3, 4 ...