Note that there are some explanatory texts on larger screens.

plurals
  1. PORecursive SQL to Create DNN Navigation Menu
    primarykey
    data
    text
    <p>I'm working on a DotNetNuke module that includes a tree-style navigation menu.</p> <p>So far, I have it working, in the sense that child-nodes are connected to their correct parent-nodes, but the node-siblings are still out of order. There's a field called TabOrder, used to determine the order of siblings, but due to the recursion, I can't get them sorted properly. </p> <p>I'm trying to do this in a SQL Server stored procedure, which may be a mistake, but I feel I'm so close that there must be a solution. Does anyone have any idea what I'm doing wrong?</p> <p>I'd appreciate any ideas you have. Thanks in advance.</p> <hr> <p><strong>Solution:</strong></p> <p>I finally found a solution to my question. The key was to recursively create a Tab Lineage (TabLevel + TabOrder) from the Root Tab to the Leaf Tabs. Once that was created, I was able to order the returned records properly.</p> <p>However, as I was coming back to post this I saw MarkXA's answer, which is probably the best solution. I didn't know the method GetNavigationNodes even existed. </p> <p>I think he is correct that using GetNavigationNodes is a more future-proof solution, but for the time being I'll use my SQL-based solution. --What can I say? I learn the hard way.</p> <p>Here it is:</p> <pre><code>ALTER procedure [dbo].[Nav_GetTabs] @CurrentTabID int = 0 AS --============================================================ --create and populate @TabLineage table variable with Tab Lineage -- --"Lineage" consists of the concatenation of TabLevel &amp; TabOrder, concatenated recursively from the root to leaf. --The lineage is VERY important, making it possible to properly order the Tab links in the navigation module. --This will be used as a lookup table to match Tabs with their lineage. --============================================================ DECLARE @TabLineage table ( TabID int, Lineage varchar(100) ); WITH TabLineage AS ( --start with root Tabs SELECT T.TabID, T.ParentID, CAST(REPLICATE('0', 5 - LEN(CAST(T2.[Level] as varchar(10)) + CAST(T2.TabOrder as varchar(10)))) + CAST(T2.[Level] as varchar(10)) + CAST(T2.TabOrder as varchar(10)) as varchar(100)) AS Lineage FROM Tabs T INNER JOIN Tabs T2 ON T.TabID = T2.TabID INNER JOIN TabPermission TP ON T.TabID = TP.TabID WHERE T.ParentID IS NULL AND T.IsDeleted = 0 AND T.IsVisible = 1 AND TP.RoleID = -1 UNION ALL --continue recursively, from parent to child Tabs SELECT T.TabID, T.ParentID, CAST(TL.Lineage + REPLICATE('0', 5 - LEN(CAST(T2.[Level] as varchar(10)) + CAST(T2.TabOrder as varchar(10)))) + CAST(T2.[Level] as varchar(10)) + CAST(T2.TabOrder as varchar(10)) as varchar(100)) AS Lineage FROM Tabs T INNER JOIN Tabs T2 ON T.TabID = T2.TabID INNER JOIN TabPermission TP ON T.TabID = TP.TabID INNER JOIN TabLineage TL ON T.ParentID = TL.TabID WHERE T.IsDeleted = 0 AND T.IsVisible = 1 AND TP.RoleID = -1 ) --insert results of recursive query into temporary table INSERT @TabLineage SELECT TL.TabID, TL.Lineage FROM TabLineage TL ORDER BY TL.Lineage OPTION (maxrecursion 10); --to increase number of traversed generations, increase "maxrecursion" --============================================================ --create and populate @Ancestor table variable with @CurrentTab ancestors -- --"Ancestors" are Tabs following the path from @CurrentTab to the root Tab it's descended from (inclusively). --These are Tab links we want to see in the navigation. --============================================================ DECLARE @Ancestor table ( TabID int ); WITH Ancestor AS ( --start with @CurrentTab SELECT T.TabID, T.ParentID FROM Tabs T WHERE T.TabID = @CurrentTabID UNION ALL --continue recursively, from child to parent Tab SELECT T.TabID, T.ParentID FROM Ancestor A INNER JOIN Tabs T ON T.TabID = A.ParentID ) --insert results of recursive query into temporary table INSERT @Ancestor SELECT A.TabID FROM Ancestor A OPTION (maxrecursion 10); --to increase number of traversed generations, increase "maxrecursion" --============================================================ --retrieve Tabs to display in navigation --This section UNIONs three query results together, giving us what we want: -- 1. All Tabs at Level 0. -- 2. All Tabs in @CurrentTab's lineage. -- 3. All Tabs which are children of Tabs in @CurrentTab's lineage. --============================================================ WITH TabNav (TabID, TabLevel, TabName, Lineage) AS ( --retrieve all Tabs at Level 0 -- (Root Tabs) (SELECT T.TabID, T.[Level] AS TabLevel, T.TabName, TL.Lineage FROM Tabs T INNER JOIN TabPermission TP ON (T.TabID = TP.TabID AND TP.RoleID = -1) INNER JOIN @TabLineage TL ON T.TabID = TL.TabID WHERE T.IsDeleted = 0 AND T.IsVisible = 1 AND T.[Level] = 0 UNION --retrieve Tabs in @CurrentTab's lineage SELECT T.TabID, T.[Level] AS TabLevel, T.TabName, TL.Lineage FROM Tabs T INNER JOIN TabPermission TP ON (T.TabID = TP.TabID AND TP.RoleID = -1) INNER JOIN @Ancestor A ON T.TabID = A.TabID INNER JOIN @TabLineage TL ON T.TabID = TL.TabID WHERE T.IsDeleted = 0 AND T.IsVisible = 1 UNION --retrieve Tabs which are children of Tabs in @CurrentTab's lineage SELECT T.TabID, T.[Level] AS TabLevel, T.TabName, TL.Lineage FROM Tabs T INNER JOIN TabPermission TP ON (T.TabID = TP.TabID AND TP.RoleID = -1) INNER JOIN @Ancestor A ON T.ParentID = A.TabID INNER JOIN @TabLineage TL ON T.TabID = TL.TabID WHERE T.IsDeleted = 0 AND T.IsVisible = 1) ) --finally, return the Tabs to be included in the navigation module SELECT TabID, TabLevel, TabName FROM TabNav ORDER BY Lineage; --============================================================ </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload