Search code examples
typo3typoscripttypo3-9.xtypo3-10.x

How to get "leveltitle" for HMENU items via TypoScript?


I have a menu (HMENU with special = updated) that gives me the latest sub and sub-sub pages from 3 categories. The page structure looks like this in the backend:

enter image description here

In addition to the title, I would like to output the name of the respective category (the parent level-1 page).

This is my TypoScript attempt:

lib.myMenu = HMENU
lib.myMenu {
    special = updated
    special{
        value.field = 10,11,12
        beginAtLevel = 1
        limit = 99
    }
    1 = TMENU
    1{
        NO{
            doNotLinkIt = 1
            stdWrap.cObject = COA
            stdWrap.cObject {
                10 = TEXT
                10{
                    wrap = <h3>|</h3>
                    field = seo_title // title
                    typolink.parameter.field = uid
                }

                20 = HMENU
                20{
                    wrap = <div class="category attempt-1">|</div>
                    special = rootline
                    special.range = 1|1
                    special.value.field = uid # does not work
                    1 = TMENU
                    1.NO.allWrap = |
                }

                30 = TEXT
                30{
                    wrap = <div class="category attempt-2">|</div>
                    data = leveltitle : 1 # does not work as expected
                }
            }
        }
    }
}

Unfortunately it does not work, because …

  1. special = rootline does not support special.value.
  2. data = leveltitle : 1 uses the ID of the current page, instead of the TMENU item ID.

Does anyone have another approach how I can get the title of the respective category using TypoScript?

Edit: Background information / what this is needed for

With this menu I intend to replace the news module ext:news of an existing project. Instead of news records, pages are now used and this menu creates the list view. Of course a TypoScript page browser will be added.


Solution

  • I have found a pure TypoScript solution that may not be very elegant, but it works:

    lib.myMenu = HMENU
    lib.myMenu {
        special = updated
        special{
            value.field = 10,11,12
            beginAtLevel = 1
            limit = 99
        }
        1 = TMENU
        1{
            NO{
                doNotLinkIt = 1
                stdWrap.cObject = COA
                stdWrap.cObject {
                    10 = TEXT
                    10{
                        wrap = <h3>|</h3>
                        field = seo_title // title
                        typolink.parameter.field = uid
                    }
    
                    20 = HMENU
                    20{
                        wrap = <div class="category">|</div>
                        special = list
                        special.value.field = pid
                        1 = TMENU
                        1{
                            NO{
                                doNotLinkIt = 1
                                stdWrap.override{
                                    # Overwrite it if we are not yet at the category level
                                    if{
                                        # The ID of the page parent to the categories ("Website") is 1618
                                        equals = 1618
                                        value.field = pid
                                        negate = 1
                                    }
                                    cObject = HMENU
                                    cObject{
                                        special = list
                                        special.value.field = pid
                                        1 = TMENU
                                        1.NO.doNotLinkIt = 1
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    

    If the menu is to go over further levels, the override must of course be nested even deeper.

    Edit – Improvements:


    RECORDS instead of HMENU: Bernd Wilke suggested in the comments to use CONTENT instead of HMENU to generate the category title. This caused problems in my tests when sysfolders (as subpages of the categories) were used to structure the items. This could be related to the bug/feature #20933 (Enable working with SysFolders in CONTENT). But RECORDS might be comparable. I tried it and was able to improve the render times a little bit (see table below).

    lib.myMenu.1.NO.stdWrap.cObject.20 = RECORDS
    lib.myMenu.1.NO.stdWrap.cObject.20{
        stdWrap.wrap = <div class="category">|</div>
        source.field = pid
        tables = pages
        conf.pages = TEXT
        conf.pages {
            field = seo_title // title
            stdWrap.override{
                # Overwrite it if we are not yet at the category level
                if{
                    # The ID of the page parent to the categories ("Website") is 1618
                    equals = 1618
                    value.field = pid
                    negate = 1
                }
                cObject = RECORDS
                cObject{
                    source.field = pid
                    tables = pages
                    conf.pages = TEXT
                    conf.pages.field = seo_title // title
                }
            }
        }
    }
    

    CONTENT instead of HMENU: if no sysfolders are needed (as of TYPO3 10.4 sysfolders should also work)

    lib.myMenu.1.NO.stdWrap.cObject.20 = CONTENT
    lib.myMenu.1.NO.stdWrap.cObject.20{
        stdWrap.wrap = <div class="category">|</div>
        table = pages
        select {
            uidInList.field = pid
            pidInList = 0
            selectFields = uid, pid, seo_title, title
        }
        renderObj = TEXT
        renderObj {
            field = seo_title // title
            stdWrap.override{
                # Overwrite it if we are not yet at the category level
                if{
                    # The ID of the page parent to the categories ("Website") is 1618
                    equals = 1618
                    value.field = pid
                    negate = 1
                }
                cObject = CONTENT
                cObject{
                    table = pages
                    select {
                        uidInList.field = pid
                        pidInList = 0
                        selectFields = uid, pid, seo_title, title
                    }
                    renderObj = TEXT
                    renderObj.field = seo_title // title
                }
            }
        }
    }
    

    userFunc instead of HMENU: Bernd Wilke suggested in his answer to use a userfunction. Even if this is not a pure TypoScript solution, I would have liked to test it to be able to compare the performance. The method getRootLine() has unfortunately been marked as deprecated. Since I'm not an extension developer, it's not clear to me yet how to read the category via a userFunc and if this is actually more effective. If I still come across a solution regarding this, it will be added here.


    Rendertime: I have test-implemented the menu in the live site (in the existing template) and compared the website render times with and without the output of the categories to see how much the nested menu affects the performance. The values are average values from 10 measurements. I also limited the output to 20 items, which should be a more realistic value per page later on:

    mode 20 items 100 items
    without category 99 ms 218 ms
    categories via HMENU 133 ms 353 ms
    categories via RECORDS 132 ms 331 ms
    categories via CONTENT 121 ms 255 ms
    categories via userFunc TBD TBD