Using a Repeater for Multi-level Accordion Navigation?


Is it (reasonably) possible to use a repeater for a multi-level, vertical accordion navigation? The nav I want to create is three levels deep.





Hmm… interesting challenge. Yes, it is ((maybe) reasonably)) possible, depending on what you need. If you post a file or example of what you’re trying to achieve it would help.

Ideally, you’d want to nest three repeater lists, but that is not supported in Axure. You could maybe nest multiple dynamic panels, each with its own repeater list, but by the time you handled when and where to move those panels around, you’d likely defeat any advantages of doing this in repeaters.

My first thought at how to achieve this would be to create a dynamic panel in your repeater cell, with three states, one for each of your nav levels. You’d style each state with different indentation, font size, color, etc. and include slots for parent content: e.g., Level 2 would have a copy of Level 1 title/content, Level 3 would have copy of Level 1 and Level 2 content. In this way, as you open an item, it would expand by changing the dp state to “Next” but not disappear–if that makes sense. With the “Fit content in HTML” option the repeater cells would automatically size themselves and push/pull locations. You’d be able to animate the accordion transitions, too. Or, you could stack the 3 dp’s, setting Level 2 and 3 to height of 0 initially, then sizing and moving them based on number of items as their parent gets selected.

In your repeater table, you’d have one column for each level, and the OnItemLoad would set text in the corresponding dp state. I guess you’d be limited to how many items you could have in Levels 2 and 3, but if you know a maximum count, like say, 20, then you could hide or move the empty item slots.

Shoots, I’m going to have to try this and post an example for any of this to make sense!

1 Like

Turns out my first thoughts were not good approaches… possible–maybe, but definitely not reasonable.

I was able to create an accordion menu with 3 levels, using filters. See this example:

AccordionRepeater2.rp (263.1 KB)


Thank you for your help. I gave your idea a try. Seems like a good approach but I can’t figure out how to add multiple level 2’s and level 3’s.

Here’s my attempt.

leftNavRepeater.rp (108.1 KB)

Source file attached.


It’s possible to do this using a system of nested item id’s.
If an item is on the second level, parentid = the id of the parent (top menu item).
If an item is on the third level, grandparentid = the id of the grandparent (top menu item).

The basic idea is:
When the user clicks on an item:

  • Set “expanded = y” for that item
  • Set “parentexpanded = y” for any items where the Targetitem.parentid ==
  • Set “grandparentexpanded = y” for any items where Targetitem.grandparentid ==

Then, add a filter to the repeater OnLoad event that shows:

  • All top-level menu items
  • Second-level menu items where the main menu is expanded
  • Third level menu items where the main menu is expanded AND the second-level menu is expanded

This is necessary if you want the inner subfolders to STAY expanded (or closed) when you close and open the main menu item. If you don’t need those inner folders to remember whether they were open or closed, you can probably simplify this.

Here’s a sample file:
leftNavRepeater_modified.rp (82.6 KB)

1 Like


Your attempt uses a different approach from mine. Granted, mine is probably more complicated than it needs to be, as most menus like this do not need to be sorted and re-sorted. Now that I’ve figured out the basics, I’ll try to simplify this, if I have the time.

In the meantime, if you use my approach as a base and look at how the repeater table is laid out, you would just copy an item from the level you need and update with your details. For instance, here is a Level 1 item, “Mineral”:

Notice the “Order” column has a number and an exclamation point, “3!” so every Level 1 item must follow this syntax --I’m using the number to allow sorting of the list (“Mineral” is the third item in Level 1) and the “!” to uniquely identify top level items in the filters when they need to be collapsed/expanded/selected (it was just easier to have at least 2 characters in this cell, but the logic could be improved, I’m sure.) Likewise, the Name column allows sorting alphabetically. This was basically to let me test how Axure handles sorting–more on that below.
If you don’t need to sort your list, the Order and Name columns aren’t technically required. You could remove these if you adjust the filter logic accordingly.

To add another Level 1 at bottom of list just increment the number and carry down the syntax used for Level 1:

Same for Level 2:

These two new items belong to “Other” which is the fourth Level 1 item, thus ordered “4”, so they are “children of 4” and inherit “4” to denote their parent. Level 2 is ordered by letter instead of number (*See below for reason) so the first item, “Liquid” gets an “a”, the next a “b” and so on. Every Level 2 item must have this same syntax.

Same for Level 3:

The Level 3 items are again sorted by number, so they inherit their parent’s “a” and their grandparent’s “4”. Again, it is just a matter of using the same syntax: all Level 3 items must have . Notice they don’t need to be directly under “Liquid” in the table, because the whole thing can be sorted later, or in the repeater’s OnLoad event to make it a default.

*I initially tried to use the “dot-number” ordering scheme, similar to what skb shows–although that whole prototype is also a different approach from mine. However, the sorting failed: all the Level 3 items went to the bottom of the list. It appears Axure interprets 1.1.1 as greater than 1.2 and 2.2 --so a properly sorted list should be:

But it turns out that sorting by “Order” ends up looking like:

This is why I resorted to using an alphanumeric multi-ordered list sort, which does get properly sorted by Axure with:

Here is a simplified accordion repeater, which uses no numbers or separate classification scheme in the repeater table.

This is the repeater structure:

All Level 1 items must have text in Level1 and empty cells in Level2 and Level3.
All Level 2 items must have parent in Level1, text in Level2 and empty Level3.
All Level 3 items must have grandparent in Level1, parent in Level2 and text in Level3.

As you can see, there is more text involved, so the setup trades off elegance for simplicity, albeit more copy & pasting. Level ownership is easy to understand, and alphabetical sorting (within levels) is still maintained.

Handling item clicks became easier and more elegant, but the filters a bit more complicated. For instance, to determine if an item is Level 1, you have to test for an empty cell in the Level2 column. To “open” a Level 1 item, it has to show all the Level 1 items and all its own child Level 2 items–but not anything else. Thus filter for “is Level 1 or (Level 2 and child of me)”. This is the click code:

…and what the filter code looks like:

…So I had to learn and pay attention to the difference between [[TargetItem.Value]] and [[Item.Value]]
Basically, in a filter the TargetItem refers to the entire repeater list; the “target” is the repeater. Item refers to a repeater cell, and in this case, since the command is coming from within the repeater cell, it basically means “my stuff” as opposed to “other rows’ stuff” --if that makes sense.

I am trying to build an interface with left navigation sidebar, based on repeater. my inspiration was file from this post.
Would it be possible to please ask you to help on the prototype where I need to the sidebar to be fully visible, when clicking on arrow? Right now, in Preview I see only closed state. Also, arrow do now rotate back foe no reason.

Thank you. Hope that you would be able to help me with theses :slight_smile:

Shell.rp (652.5 KB)

Shell_EDIT.rp (652.9 KB)
From Chelsea (Axure support):
You already have an OnLoad interaction on your sidebar’s repeater that filters the menu to hide all of your repeater options:

The OnLoad case for the “Navigation with sections” repeater filters the navigation sections so that when the page is loaded, none of the repeater options are visible. I’m going to add an additional action to the “label.L1-2” rectangle so that the filter is removed:

Then, for the second case for “label.L1-2”, I’m going to fire the OnLoad for “Navigation with sections”, so that the filter is added, and the menu options are hidden once again:

Lastly, I’ve added actions to both cases for this rectangle so that the first case sets the selection of “label.L1-2” to “true”, and the second case sets the selection to “false”. This effectively allows the cases to toggle between each other, which in turn allows the repeater to filter and unfilter. This also resolves the issue with your arrow not rotating back.

That is one complex repeater!

I can’t really tell what’s going on with the repeater–there is just so much there. Looks like the repeater OnLoad has a filter that collapses it. If you remove all filters on the repeater, it shows all levels (which means sidebar is fully visible, I assume.)

The code you have for the “Campaign Automation” widget (which sits on top of the caret) doesn’t immediately make sense to me… The OnClick has two cases which test whether it is selected or not, but I can’t see that it ever gets selected, and there is no style for a selected state, so no way to tell for sure. There is also no code for OnSelected, OnUnSelected or OnSelectedChange so I don’t think you’re really doing anything there.

The caret has a rotation up for OnSelected and a rotation down for OnUnselected, so you’re better off testing against that. However, in that Campaign Automation code you Rotate the caret instead of changing its selection state, which is very confusing–you should just set the caret to selected or unselected and use that to control rotation–otherwise very hard to track what will or should happen there.

Looks like you are applying several filters which are doing the opposite? …Or nothing at all? The filters are testing against global variables which are not initiated (blank) on page load, so the first click would not apply either filter. I can’t tell if they would ever be sufficed…

To test some basic opening and closing of the sidebar (your Navigation with sections repeater widget) I moved your OnClick code to OnResize for safekeeping. I copied the “Level 1” filter from the repeater’s OnLoad and used that in the label.L1-2 OnClick, then tested against the caret.L1-peretz selection state. That at least opens and closes the sidebar. Maybe you can add back in the code lines that make sense to you and proceed from there…

Shell.rp (665.2 KB)

Thank you so much for your help and feedback!!! I started to work on this navigation 2 days ago, and I am trying to mimic real navigation that really complex.

I am doing it in stages. I will post my progress, as I’ll go forward.

Hi mbc66 :slight_smile:

Thank you for helping me with this difficult repeater-sidebar.

I worked all day on it and made a good progress. :slight_smile:

Shell-to expend.rp (681.4 KB)

But I stuck again on two things that I can’t figured out. :frowning:

In real application ‘on page load’ condensed sidebar always visible and “Overview” icon is selected like that:

If user enter mouse over sidebar it become extended:

and if user clicks on any of All tools/Top pages:

‘Overview’ page always selected.

In my prototype on page load all items under CA are not visible, and I like to make them visible

Another issue I have, when I select anything, other choices are become invisible and state ‘Campaign Automation’ jump to state ‘CA’.

Thank you again for your help,

It looks like you’ve got most of this figured out. Nice job.

I would recommend just making the size of sidebar 64 px wide on the page. The OnMouseEnter event will size it to 280 px and you’re good to go. I assume it should collapse again when the mouse cursor is not over the sidebar, so you could add an OnMouseOut event, too. Likewise, most of your OnPageLoad actions can just be set up in the editor (and some of them already are…)

So, the first item under “Campaign” should be selected by default. That can be handled in the OnItemLoad for the repeater to set that row’s column for “Selected”. Looking at the Nav repeater, this is already set up (the row for “Overview” has a “Selected” column set to “true” and the text widget has a Selected style) but just needs a condition to assign the selected state. I’m not sure why the “Class” column has “3” for all the items which seem to be Class/Level2, but we can use that to identify the right item (label.L2a; This widget should also have a Selection Group defined so that only one instance of these (e.g., “Overview”) can be selected.) The blank OnItemLoad event that you’ve started should be something like:
If [[Item.Class]] = "3" and [[Item.Selected]] = "true" set is selected of label.L2a to "true"

An Update Rows action can set that row’s column for “Selected” to “yes”:
[[Item.ClassL2atext == 'Overview']] and assign the “Selected” column to “true”.

Get rid of the Add Filter Level 1 action in the Nav repeater’s OnLoad event. That is what is collapsing it.

Take a look at the code for that widget, label.L2a --there is a bunch of stuff there which I don’t understand, but one of those Update Rows or Add Filter actions is likely collapsing it (maybe by triggering that OnLoad action which shouldn’t be there. Also, that “Campaign Automation” dp has a default state of “CA” so anytime the repeater is updated, it would reset to the first state. So, I would move “Campaign Automation” to the first state to handle that. You also set the state to CA in your OnPageLoad event, so that should work.

Hi mbc66,

Thank you so much for all of your great suggestions!

I was able to fix the majority of issues based on them. Truly appreciate it! :slight_smile:

I have just a few more issues. If you could please give me your expert advice on them, would greatly appreciate it.

Shell-4.rp (1.2 MB)

  • The initial view of the sidebar contains some strange spaces in the repeater (it happened after I removed filter actions code).

  • When the sidebar is expanded, with Campaign Automation label expanded, clicking on one of the repeater choices under the Overview triggers the Campaign Automation label switch to CA

  • When the “All tools” is expanded and the “All tools” entry named ‘Campaign Automation’ is expanded via the caret as well, the content of the entire expanded entry is repeated vertically.

  • In the “group.L1” that belongs to the first level of the sidebar navigation, I need to have a specific ‘Top pages’ action: when user clicks on this menu item, the “sidebar-filters” panel is opened on the “Top pages” state. Not sure how to do this.

  • I have one more question: on second page of attached file I included Nested repeater. I do not know if I can use this technics for creation extension-menu like that:

Here is a Recording from real shell navigation

Thanks again,

Not sure what is going on there… You do have two competing actions that set the size of sidebar dp to 64 px (OnPageLoad) and 65 px (OnLoad for sidebar). I removed both and these gaps don’t show up. Somehow the repeater is changing when sidebar width changes. I suspect this is a collision of the repeater loading at the same time its container is changing. I set the default width of sidebar to 64px and the gaps don’t show up. I don’t know what you’re trying to do with the invisible shape widget but putting the “set size of sidebar to 280” on it instead of sidebar itself creates a “back and forth bouncing” of the width. Better to keep the resizing actions on the sidebar’s OnMouseEnter and OnMouseExit.

That doesn’t happen for me… (Win 10, Chrome) …Maybe fixes above fix this, too?

On your group.L1 widget (which would either be 'Class 1, Order 1! : “All Tools” ’ or ’ Class 1, Order 2! : “Top pages” ’ you could test 'If [[Item.Order]] contains “2” ’ and then set your sidebar-filters dp to the correct state and show it.

Hmm… You cannot nest repeaters in Axure, so this looks like some approach to mimic that, using multiple states of a dynamic panel within a repeater? Yes, you could have a hidden dp with N states (N = number of Class 3 widgets in your menu) which gets shown when you click one of those menu items, then when hovered show a group of widgets as the “expanded state” like you show for “New” above. This would get pretty complex to list all that out in your repeater sheet (adding columns for all that) which is already pretty complicated. …And you’d have to deal with the width of sidebar when showing/hiding all that… I would try creating a separate repeater for this flyout menu and coordinating selection/states with the Nav repeater. So, when “Email” is clicked, the corresponding “Email” row or dp state is set and shown.

From Axure Support (Simon):
First, I changed the condition of the first case of the “Navigation with sections” repeater’s OnItemLoad event (named “Campaign automation”) to evaluate for “Item.Class” instead of “Item.ClassL1text” to avoid confusion, since the value stored in the ClassL1text column of the first item is “2” as well. Then in the Set Panel State action of the same case, I edited it so that it would set the panel state of the “CA-title” dynamic panel to the value stored in the repeater item’s “Level1a” column:

This makes it so that the CA-title panel is set to which ever state’s name matches the value stored in the Level1a column (e.g. if the value in Level1a is “Campaign Automation”, the panel will be set to the “Campaign Automation” state). Because the values of these names will need to match up exactly, you’ll want to change the state currently titled “Compaign Automation” to “Campaign Automation” instead.

Then, to complete this interaction, you’ll want to add “Update Row” actions that change the value stored in the Level1a column to the CA-title panel’s corresponding state. I ended up adding these to the “OnMouseEnter” and “OnMouseOut” events of the “sidebar” dynamic panel and “invisible shape” group respectively, since these seem to be the main events determining which label should be displayed:

That’s it; now mousing in to the sidebar will update the Level1a column’s value to “Campaign Automation” and set the label to this value as well, and mousing out of the invisible shape group will do the same for the “CA” label. Since the appearance of the label is now only determined by the value in this column (thanks to the first adjustment made in the OnItemLoad event), the label will persist even when the repeater items are reloaded. Overall this interaction does have a few different elements to it, so feel free to use my edited file as a reference point.

Also, if you’re interested in learning more about how the set panel state portion of this approach is working, the following tutorial may help:

Shell-7_edited.rp (1.1 MB)

As for your submenu, it looks like only six items are showing because the hot spot widget within the repeater is currently setting the size of the “sub” dynamic panel to the height value of “[[LVAR1.height * 6]]”, where it looks like “LVAR1” is referring to the size of one subentry rectangle. This is limiting the panel to a size that’s only be able to show six submenu items:

Since the “Reports” submenu contains seven items, the last item won’t appear in this case. To fix this, you’ll want to change the height so that it’s instead being set to “[[LVAR1.height * 7]]”. Note that if you end up creating a submenu with more than seven items, you’ll want to change this again to match the new maximum number of submenu items.
submenu-question.rp (298.5 KB)

Hi mbc66,
Thank you for all your suggestions!
I am back with new questions :slight_smile:

shell nav with flyout menu.rp (1004.2 KB)

I am trying to achieve action that by clicking on any items on menu corresponding flyout sub-menu appear.

From my file:

I think I need expert help, because I lost :frowning: :frowning: :frowning:

If you could please help me out with the above issue, I would greatly appreciate it!

Thank you so much!

See if this helps:
shell nav with flyout menu.rp (1.1 MB)

I took all your hidden flyout menu repeaters and put them in states for a “SubsetMenu” dp. Clicking on an L2 item in the left nav will set the SubsetMenu dp to the state with it’s text label (as defined by [[Item.ClassL2text]]) and moves that dp to its y-location. So, I don’t think you need the last two cases in your OnItemLoad event, and you don’t need the FlyoutMenuOrder column.

1 Like

Absolutely. Wow! This is such a great and simple solution!
Thank you so very much, mbc66!!! :slight_smile:

Hi there,

I have been trying to achieve what you guys are talking about. And to be frank I am blown away with the complexity of those queries.

I have made the repeater as @mbc66 suggested and tried to copy the queries but somehow it doesn’t work.

The pattern I am trying to do:
There is a list of Level 1 items
When you tap on one
All Child of the selected item are displayed
As you select a child it changes state to look like Level1
and so on…

Here is the motion

Here is my file
accordion-inception (261.7 KB)

So if you have a minute to help a fellow axure folk :slight_smile: please help me out