renet
I'm new here

Dynamic definition of root in Navigation function

Jump to solution

Hello community,

I have the following problem: I want to render

- the complete navigation tree (expansionVisibility=all),

- but only for the selected 1st level node and

- no matter which sub-nodes of that 1st level node are selected (wholePathSelected=1)

Therefore I need to

- either dynamically set the root parameter

- or set the level that the navigation should start at (meaning: show only level 2+ nodes only under the selected 1st level node).

Does the Navigation function offer either of these possibilities? I didn't find anything about this in the documentation/help.

Right now my Navigation function looks as follows:

<CMS_FUNCTION name="Navigation" resultname="fr_dtn">

    <CMS_PARAM name="expansionVisibility" value="all"/>

    <CMS_PARAM name="wholePathSelected" value="1"/>

    <CMS_PARAM name="suppressEmptyFolders" value="1" />

    <CMS_ARRAY_PARAM name="innerBeginHTML">

        <CMS_ARRAY_ELEMENT index="1..9"><![CDATA[<ul>]]></CMS_ARRAY_ELEMENT>

    </CMS_ARRAY_PARAM>

    <CMS_ARRAY_PARAM name="innerEndHTML">

        <CMS_ARRAY_ELEMENT index="1..9"><![CDATA[</ul>]]></CMS_ARRAY_ELEMENT>

    </CMS_ARRAY_PARAM>

    <CMS_ARRAY_PARAM name="endHTML">

        <CMS_ARRAY_ELEMENT index="1..9"><![CDATA[</li>]]></CMS_ARRAY_ELEMENT>

    </CMS_ARRAY_PARAM>

    <CMS_ARRAY_PARAM name="unselectedHTML">

        <CMS_ARRAY_ELEMENT index="1..9">

            <![CDATA[

                ...

            ]]>

        </CMS_ARRAY_ELEMENT>

    </CMS_ARRAY_PARAM>

    <CMS_ARRAY_PARAM name="selectedHTML">

        <CMS_ARRAY_ELEMENT index="1..9">

            <![CDATA[

                ...

            ]]>

        </CMS_ARRAY_ELEMENT>

    </CMS_ARRAY_PARAM>

</CMS_FUNCTION>

But this way the sub-nodes of all 1st level nodes that are not selected will be rendered, as well.

My only solution (hopefully) for this problem seems to be to add something like

<CMS_ARRAY_PARAM name="unselectedHTML">

    <CMS_ARRAY_ELEMENT index="0">

        <![CDATA[$CMS_SET(1st_level_selected,false)$]]>

    </CMS_ARRAY_ELEMENT>

    <CMS_ARRAY_ELEMENT index="1..9">

        <![CDATA[

            $CMS_IF(1st_level_selected)$

                ...

            $CMS_END_IF$

        ]]>

    </CMS_ARRAY_ELEMENT>

</CMS_ARRAY_PARAM>

<CMS_ARRAY_PARAM name="selectedHTML">

    <CMS_ARRAY_ELEMENT index="0">

        <![CDATA[$CMS_SET(1st_level_selected,true)$]]>

    </CMS_ARRAY_ELEMENT>

    <CMS_ARRAY_ELEMENT index="1..9">

        <![CDATA[

            $CMS_IF(1st_level_selected)$

                ...

            $CMS_END_IF$

        ]]>

    </CMS_ARRAY_ELEMENT>

</CMS_ARRAY_PARAM>

Is this the only possible solution? Thank you for your replies in advance!

Regards,

René Schubert

1 Solution

Accepted Solutions
hoebbel
Crownpeak employee

Hello Mr. Schubert,

René Schubert schrieb:

I have the following problem: I want to render
- the complete navigation tree (expansionVisibility=all),

- but only for the selected 1st level node and

- no matter which sub-nodes of that 1st level node are selected (wholePathSelected=1)

I would do it using two navigation functions.

The first function is to dynamically define the start folder:

<CMS_FUNCTION name="Navigation" resultname="fr_pt_getrootfolder">

<CMS_PARAM name="expansionVisibility" value="purepath"/>

<CMS_PARAM name="wholePathSelected" value="1"/>

<CMS_ARRAY_PARAM name="selectedHTML">

<CMS_ARRAY_ELEMENT index="0">$CMS_VALUE(#nav.folder.referenceName)$</CMS_ARRAY_ELEMENT>

</CMS_ARRAY_PARAM>

</CMS_FUNCTION>

The second one is for the output itself:

<CMS_FUNCTION name="Navigation" resultname="fr_sc_navigation">

<CMS_VALUE_PARAM name="root" value="fr_pt_getrootfolder.toString()"/>

<CMS_PARAM name="expansionVisibility" value="all"/>

<CMS_PARAM name="wholePathSelected" value="1"/>

<CMS_ARRAY_PARAM name="selectedHTML">

<CMS_ARRAY_ELEMENT><![CDATA[-"$CMS_VALUE(#nav.id + " " + #nav.label)$"-<br>]]></CMS_ARRAY_ELEMENT>

</CMS_ARRAY_PARAM>

<CMS_ARRAY_PARAM name="unselectedHTML">

<CMS_ARRAY_ELEMENT><![CDATA["$CMS_VALUE(#nav.id + " " + #nav.label)$"<br>]]></CMS_ARRAY_ELEMENT>

</CMS_ARRAY_PARAM>

</CMS_FUNCTION>

But you may get problems, if you use startfolders or if you hide menu entries from the navigation.

Best regards,

  Holger Höbbel

View solution in original post

0 Kudos
8 Replies
martin_herschke
I'm new here

Both ways should be possible.

First:

The level you want to show can be defined by changing the index values within:

<CMS_ARRAY_ELEMENT index="1..9">

into something else:

<CMS_ARRAY_ELEMENT index="2..4">

resulting in a navigation menu for the second to fourth level

Second:

if you want to skip the output for unselected items within your "wholePathSelected" navigation, just skip the

<CMS_ARRAY_PARAM name="unselectedHTML">

element. As an alternative, you could add-&-modify the

<CMS_PARAM name="expansionVisibility" value="pathonly" />

parameter.

Third:

You could change the root parameter using implicit objects:

<CMS_PARAM name="root" value="#global.node" />


Optionally, you can extract the whole navigtion header function into a separate template using only the $CMS_RENDER(template:"<yourTemplateName>", param_root: <anySitestoreFolder>)$ command to refer to it.Then you can use the extra parameter (param_root) within your template.

<CMS_PARAM name="root" value="param_root" />


This could also reduce the number of navigation functions you have to implement.

Keep in mind:

All the navigation function does is to create a "forEach" loop calling the "getChildren()" and the "isFolder()" methods. You could easily reproduce the navigation function with the normal $CMS_FOR()$ and $CMS_VALUE()$ commands.

Hope I could help you

Martin Herschke

hoebbel
Crownpeak employee

Hello Mr. Schubert,

René Schubert schrieb:

I have the following problem: I want to render
- the complete navigation tree (expansionVisibility=all),

- but only for the selected 1st level node and

- no matter which sub-nodes of that 1st level node are selected (wholePathSelected=1)

I would do it using two navigation functions.

The first function is to dynamically define the start folder:

<CMS_FUNCTION name="Navigation" resultname="fr_pt_getrootfolder">

<CMS_PARAM name="expansionVisibility" value="purepath"/>

<CMS_PARAM name="wholePathSelected" value="1"/>

<CMS_ARRAY_PARAM name="selectedHTML">

<CMS_ARRAY_ELEMENT index="0">$CMS_VALUE(#nav.folder.referenceName)$</CMS_ARRAY_ELEMENT>

</CMS_ARRAY_PARAM>

</CMS_FUNCTION>

The second one is for the output itself:

<CMS_FUNCTION name="Navigation" resultname="fr_sc_navigation">

<CMS_VALUE_PARAM name="root" value="fr_pt_getrootfolder.toString()"/>

<CMS_PARAM name="expansionVisibility" value="all"/>

<CMS_PARAM name="wholePathSelected" value="1"/>

<CMS_ARRAY_PARAM name="selectedHTML">

<CMS_ARRAY_ELEMENT><![CDATA[-"$CMS_VALUE(#nav.id + " " + #nav.label)$"-<br>]]></CMS_ARRAY_ELEMENT>

</CMS_ARRAY_PARAM>

<CMS_ARRAY_PARAM name="unselectedHTML">

<CMS_ARRAY_ELEMENT><![CDATA["$CMS_VALUE(#nav.id + " " + #nav.label)$"<br>]]></CMS_ARRAY_ELEMENT>

</CMS_ARRAY_PARAM>

</CMS_FUNCTION>

But you may get problems, if you use startfolders or if you hide menu entries from the navigation.

Best regards,

  Holger Höbbel

0 Kudos

Martin Herschke schrieb:

Keep in mind:

All the navigation function does is to create a "forEach" loop calling the "getChildren()" and the "isFolder()" methods. You could easily reproduce the navigation function with the normal $CMS_FOR()$ and $CMS_VALUE()$ commands.

The navigation function checks, if there are start nodes [and correctly links them], if navigation folders should be shown on the front end and some more "magic". I think, that it is possible to reproduce the navigation function with template syntax, but it will be a little bit more complex then just some $CMS_FOR()$ and $CMS_VALUE()$ commands Smiley Wink

0 Kudos

@Martin Herschke: First and Second were not, what I was looking for. This was not applicable to my problem, as I needed all (also the non-selected) subnodes of a certain node to be rendered. But I did not want subnodes of brother-nodes of this certain node to be rendered, either. The third hint was quite interesting, and is not yet documented. Thanks for that, maybe I can use this in the future for similar problems.

@Holger Höbbel: Thank you, that was exactly what I was looking for. Too bad that there is no easier way to define the level on which the selected node should be used as root node. And also, too bad that it's not possible to process the root node itself inside the Navigation function.

Regards,

René Schubert

0 Kudos
hoebbel
Crownpeak employee

Hello Mr. Schubert,

René Schubert schrieb:


@Holger Höbbel: Thank you, that was exactly what I was looking for. Too bad that there is no easier way to define the level on which the selected node should be used as root node. And also, too bad that it's not possible to process the root node itself inside the Navigation function.


If you do want to create an entry for the root node, you can use the information from the first navigation and create the entry before the output of the navigation:

<Navigation Entry HTML CODE>$CMS_REF(fr_pt_getrootfolder.toString())$<Navigation Entry HTML CODE>

$CMS_VALUE(fr_sc_navigation)$

Best regards,

  Holger Höbbel

0 Kudos

Hi,

I have one issue with this solution. If a page is not referenced in the Sitestore, it causes a preview error (because the first function returns an empty String:

(header function 'Navigation', resultname = 'fr_detailed_navigation' at 18, 2):  at 18, 2: invalid value for parameter 'root', invalid reference '')

Interesting: even if the function is not called the function (remove the CMS_VALUE(fr_detailed_navigation) from the template) the error still remains - so I could not do any workarounds wih if-statements to repress the error message..

Any Ideas ?

Greetings,

Michael

0 Kudos
hoebbel
Crownpeak employee

Hello Michael,

if a page is not referred within the sitestore, you cannot determine the first level folder, since there is none.

That the error remains, even if the function is not called, is probably due to a "preexecution" of the function [it is executed before the content is created]

A possible Workaround (not tested) could be this:

<CMS_VALUE_PARAM name='root' value='if(fr_pt_getrootfolder.isSet,fr_pt_getrootfolder.toString(),"pagefolder:root"'/>

You can use any pagefolder name (root = sitestore root)

Attention: You have to use two types of ticks here (' and ")

If you just want to avoid the error, try to transfer the two function (and their output) to a format template and check, if the page is referred within the sitestore before calling the formattemplate.

Disadvantage: You have to put the whole output within this format template, since it has a lower generation context, so that the there defined variables are not available within the page/section template

Best regards,

  Holger

Hi Holger,

thanks!

the first way did not work properly (error was gone, but nothing has been rendered) -  the second possibily works fine for me! :smileycool:

Greetings,

Michael

0 Kudos