# Update Navigation First Tier Tabs

**URL:** <https://forum.inductiveautomation.com/t/update-navigation-first-tier-tabs/94110>\
**Category:** Ignition\
**Tags:** vision\
**Created:** [August 2, 2024, 12:31pm UTC](https://forum.inductiveautomation.com/t/update-navigation-first-tier-tabs/94110 "2024-08-02T12:31:34Z")\
**Posts on this page:** 1\
**Showing post:** 6

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [August 6, 2024, 2:20pm UTC](https://forum.inductiveautomation.com/t/update-navigation-first-tier-tabs/94110/6 "2024-08-06T14:20:52Z")

</div>

This is going to be highly dependent on how the navigation was set up. That said:

First off, I want to let you know that I've had to full-scale redo 2-tier navigation 3 times with this project until I got it down. It's pretty well "final" at this point in time. It's made in a way that also allows [multiple desktops](https://forum.inductiveautomation.com/t/mutli-monitor-to-show-4-different-display/93034/5), as has been discussed on this forum a couple of times. I'll link to that as well.

It's not super straightforward, or intuitive, but it gets the job done and allows for context buttons as well, and is pretty flexible.

Here's what I've come up with.

Docked navigation window custom properties:

1. `currentTier1` : INT
2. `currentWindow` : STRING
3. `designer` : BOOL | `{[System]Client/System/SystemFlags} = 1`

Docked navigation window components:

1. `Tier1` : Tab Strip  
a. Navigation Mode, disabled  
b. The "Window Name" for each tab is the tier 1 index (INT)  
c. Add a custom "Tier2" (STRING) column to the `tabData` with a path to the  
"main" window for that tier.  
d. `selectedTab` bidirectionally bound to the custom `currentTier1` prop.
2. `Tier2` : Tab Strip  
a. Navigation Mode, swap windows  
b. `selectedTab` bidirectionally bound to the custom `currentWindow` prop.  
c. Configure appearances as desired
3. `Tier2_1` : Tab Strip  
a. Configure these 2nd tier tab strips using the customizer. These tab strips will be off-screen and the `tabData` will be transferred to `Tier2` as needed.  
b. Bind the `visible` property to the `designer` custom prop.
4. ...
5. `Tier2_X` : Tab Strip

A few scripts, in a library of course:

```python
dockedNavPath = 'Nav'

def tier1MouseClicked(tabStrip, selectedTab = None):
	'''
	Swap window from the docked 1st tier navigation tab. 1st tier tabStrip must include "Tier2" column with path to the main window.
		
		Args:
			tabStrip (Tab Strip obj)	:	1st tier tab strip object. (event.source)
																	Must include custom "Tier2" column in tabData dataset
			seledctedTab (INT) :	Selected first tier tab. (optional, default uses tabStrip.selectedTab)
																	(0-based index for tabData dataset)
			
		Returns:
			n/a
			*Nav.Root Container.currentWindow	(string) :	update navigation docked view current window
	'''
	#selected tab not specified, use selectedTab prop on tab strip
	if selectedTab is None:
		selectedTab = tabStrip.selectedTab
		
	#get window path
	tier1 = int(selectedTab)
	windowPath = tabStrip.tabData.getValueAt(tier1,'Tier2')
	
	#special condition example
	if windowPath == 'SLDG-10 SLUDGE OVERVIEW':
		area = system.tag.readBlocking('[client]Areas/Station_Area')[0].value
		if not area == 0:
			windowPath = 'Phase_2B/10-RAS_WAS/RAS_WAS'
			
	#special condition example
	elif windowPath == 'Phase_2B/09-Final Clarifiers/Overview':
		area = system.tag.readBlocking('[client]Areas/Station_Area')[0].value
		if not area == 0:
			windowPath = 'Phase_2B/02-Waste/INP'
			
	#swap to window and update properties
	contextNavButtonClicked(tier1, windowPath)
	

def contextNavButtonClicked(tier1, windowPath):
	'''
	Swap windows from a context navigation button.
	
	Args:
		tier1 (string)	:	0-based index for tier 1 tab strip
		windowPath (string)	:	window to swap to
	
	Returns:
		n/a
	'''
	#swap to window
	system.nav.swapTo(windowPath)
	
	system.util.invokeLater(lambda : setDockedNavSelections(tier1,windowPath), 200)
	

def setDockedNavSelections(tier1, windowPath):
	'''
	Set root container props on the docked navigation view for tier 1 and tier 2 nav strips.
	
	Args:
		tier1 (string)	:	0-based index for tier 1 tab strip
		windowPath (string)	:	current window
		
	Returns:
		n/a
		*Nav.Root Container.currentWindow	(string)	:	update navigation docked view current window
		*Nav.Root Container.currentTier1	(string)	:	update navigation docked view tier 1 tab
	'''
	
	#update tier 1 and tier 2 props
	dockedNavRootContainer = system.gui.getWindow(dockedNavPath).getComponentForPath('Root Container')
	dockedNavRootContainer.currentTier1 = tier1
	dockedNavRootContainer.currentWindow = windowPath

```

Docked navigation window scripting:

1. `visionWindowOpened()` : set up a script to set the initial `Tier1` tab as desired

```python
#set the initial tier 1 navigation to tab "0"
Common.Nav.tier1MouseClicked(system.gui.getParentWindow(event).getComponentForPath('Root Container.Tier1'), 0)

```

1. `Tier1.mouseClicked()` : call tier 1 mouse click library script

```python
Common.Nav.tier1MouseClicked(event.source)

```

1. `Tier1.propertyChange()` : assign `tabData` for `Tier2` to the associated `Tier2_X` tab strip `tabData`.

```python
if event.propertyName == 'selectedTab':
	
	selectedTab = event.source.selectedTab
	
	event.source.parent.getComponent('Tier2').tabData = event.source.parent.getComponent('Tier2_'+selectedTab).tabData

```

Looks something like this, with all of the sub-strips visible

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/1/a177dd183f1348a1eac6084df3ffccf69789537f.png)  
Just change the window height to hide the sub-tabs.  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/b/eb9c5da5c881ff924d22c68a8f4aeb19944428b3.png)

A context navigation button's script would look like this:

```python
Common.Nav.contextNavButtonClicked(0, '0/Sub_1')

```

I would recommend defining some constants in the script library to use, instead of the hardcoded "0".

Results (simple example):  
 ![Tier2_Nav](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/f/1fbbada453d72acb5811a2105c8fa1865363eb03.gif)

---

_[View the full topic](https://forum.inductiveautomation.com/t/update-navigation-first-tier-tabs/94110)._
