# Perspective Horizontal Menu Component

**URL:** <https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269>\
**Category:** Ignition Early Access\
**Created:** [May 23, 2019, 6:11pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269 "2019-05-23T18:11:51Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![wking](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/wking/32/21823_2.png) [@wking](https://forum.inductiveautomation.com/u/wking)\
**Post date:** [January 22, 2020, 5:08am UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/21 "2020-01-22T05:08:14Z")

</div>

One more.

Trying to just pass props.items[x].enabled and start there.

It works but in testing in my browser:  
land on the page unauthenticated and menu items are unavailable. Good.  
Hit a header icon that runs system.perspective.login() and go to login screen and login. Come back and menu items still are not enabled.  
Switch to console in browser and make app switch to small break-point and back to reload the **header view** and the menu items are enabled now.

Maybe expected behavior although I’d think the view would reload during login. But, how could you get the behavior of enabled menu items after login without reloading view or call .login and .reload with the header icon that goes to login? Or how to get a new session-id? Can’t reload view on start-up script lol

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [January 22, 2020, 3:08pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/22 "2020-01-22T15:08:31Z")

</div>

Why don’t you bind against the user’s authentication values and/or permissions, then use a transform to construct the structure?

---

<div class="post-metadata">

**Author:** ![wking](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/wking/32/21823_2.png) [@wking](https://forum.inductiveautomation.com/u/wking)\
**Post date:** [January 22, 2020, 3:26pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/23 "2020-01-22T15:26:51Z")

</div>

I think that is the plan…  
I originally had a binding on the items enabled prop. Bound to session.props.auth.user.roles and could only get it to work by closing page completely and reloading to make menu items enable after login(). But, I wasn’t calling a refresh binding on it anywhere. I need to add to the startup script maybe and try it out that way. But, if the start-up script of view doesn’t run after login (like above) then it won’t help.

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [January 22, 2020, 3:29pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/24 "2020-01-22T15:29:51Z")

</div>

As kind of a weird workaround, you could bind some custom property to the session.auth.username property, then put an onChange script on this custom property to invoke refreshBinding on the props.items property.

---

<div class="post-metadata">

**Author:** ![djones](https://avatars.discourse-cdn.com/v4/letter/d/43a26b/32.png) [@djones](https://forum.inductiveautomation.com/u/djones)\
**Post date:** [August 29, 2020, 9:05pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/25 "2020-08-29T21:05:57Z")

</div>

what would this structure look like. I get the idea of using a transform script to create the “items” structure and using the users authentication as a binding and effectively a trigger.

I could add additional items based on their roles, for example.

I’m just not sure how to build the structure to bind to props.items

---

<div class="post-metadata">

**Author:** ![djones](https://avatars.discourse-cdn.com/v4/letter/d/43a26b/32.png) [@djones](https://forum.inductiveautomation.com/u/djones)\
**Post date:** [August 29, 2020, 9:15pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/26 "2020-08-29T21:15:40Z")

</div>

Not sure if this is right, but it seems to be working

```auto
list = []
list.append({"enabled":True,"target":'',"label":'Item1',"items":[],"icon":[]})
list.append({"enabled":True,"target":'',"label":'Item2',"items":[],"icon":[]})
		
self.parent.parent.parent.getChild("CoordinateContainer").getChild("HorizontalMenu_0").props.items = list

```

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [August 31, 2020, 4:41am UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/27 "2020-08-31T04:41:16Z")

</div>

While that will technically work, I advise against using `list` as a variable name because “list” is a type in Python. You run the risk of encountering some errors/exceptions which could seem nonsensical given that variable name.

---

<div class="post-metadata">

**Author:** ![djones](https://avatars.discourse-cdn.com/v4/letter/d/43a26b/32.png) [@djones](https://forum.inductiveautomation.com/u/djones)\
**Post date:** [August 31, 2020, 3:06pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/28 "2020-08-31T15:06:09Z")

</div>

What, may I ask, is the right way? because this works in the designer, but I get a Component Error in chrome.

---

<div class="post-metadata">

**Author:** ![djones](https://avatars.discourse-cdn.com/v4/letter/d/43a26b/32.png) [@djones](https://forum.inductiveautomation.com/u/djones)\
**Post date:** [August 31, 2020, 3:12pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/29 "2020-08-31T15:12:19Z")

</div>

Sorry, I just realized you wanted me to change the variable name. This is done, however, I still get an error in chrome. I am limiting the Horizontalmenu items with a Transform Script. If an user with admin role is logged in, they should get extra menu options

```auto
	uName = self.session.props.auth.user.userName
	roles = self.session.props.auth.user.roles
	isGELT = 0
	isAdmin = 0 
	
	for role in roles:
		if role == 'Administrator':
			isAdmin = 1
			isGELT =1
		elif role == 'TT_Admin':
			isAdmin = 1
			isGELT =1
		elif role =='TT_GELT':
			isGELT = 1
		
	
	l = []
	#File
	l.append({"enabled":True,"target":'',"label":'File',"icon":{"path":''},"items":[],"style":{"classes":''}})
	l[0]['items'].append({"enabled":True,"target":'',"label":'Logout',"icon":{"path":''},"items":[]})
	#Admin
	if isAdmin ==1:
		l.append({"enabled":True,"target":'',"label":'Admin',"icon":{"path":''},"items":[],"style":{"classes":''}})
		l[i]['items'].append({"enabled":True,"target":'/Users',"label":'User List',"icon":{"path":''},"items":[],"style":{"classes":''}})
		
		i=i+1
    return l

```

It works in the designer, but I get the following error in chrome with a Component Error.

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/7/a/7a340be1d15d0ef9abe18983aaa0cc0de1fa79cb.png)

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [August 31, 2020, 3:16pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/30 "2020-08-31T15:16:15Z")

</div>

I’m surprised that’s working in the Designer because you reference a variable (`i`) before it’s ever defined.

This line right here:

```auto
l[i]['items'].append({"enabled":True,"target":'/Users',"label":'User List',"icon":{"path":''},"items":[],"style":{"classes":''}})

```

should fail even in the Designer because you have not defined `i` before you use it.

---

<div class="post-metadata">

**Author:** ![djones](https://avatars.discourse-cdn.com/v4/letter/d/43a26b/32.png) [@djones](https://forum.inductiveautomation.com/u/djones)\
**Post date:** [August 31, 2020, 3:31pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/31 "2020-08-31T15:31:58Z")

</div>

sorry, that was a cut and paste error. i is defined in my code. I just didn’t want you to see everything in between. Here is what i have at the moment, working in the designer, not working in chrome

```auto
	
	uName = value
	roles = self.session.props.auth.user.roles
	
	isGELT = 0
	isAdmin = 0 
	
	for role in roles:
		if role == 'Administrator':
			isAdmin = 1
			isGELT =1
		elif role == 'TT_Admin':
			isAdmin = 1
			isGELT =1
		elif role =='TT_GELT':
			isGELT = 1
		
	
	l = []
	
	#File
	l.append({"enabled":True,"target":'',"label":'File',"icon":{"path":''},"items":[],"style":{"classes":''}})
	l[0]['items'].append({"enabled":True,"target":'',"label":'Logout',"icon":{"path":''},"items":[]})
	
	i=1

	#Admin
	if isAdmin == 1:
		l.append({"enabled":True,"target":'',"label":'Admin',"icon":{"path":''},"items":[],"style":{"classes":''}})
		l[i]['items'].append({"enabled":True,"target":'/Users',"label":'User List',"icon":{"path":''},"items":[],"style":{"classes":''}})
		i=i+1
				
	return l

```

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [August 31, 2020, 3:40pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/32 "2020-08-31T15:40:20Z")

</div>

Two things I had to change in your script to get it working on my end:  
1.

```auto
    # If user is not authenticated then roles is null/None, and therefore not iterable
	if roles:
		for role in roles:
			if role == 'Administrator':
				isAdmin = 1
				isGELT =1
			elif role == 'TT_Admin':
				isAdmin = 1
				isGELT =1
			elif role =='TT_GELT':
				isGELT = 1
		

```

1. Maybe a copy/paste issue, but the `return l` statement was tabbed too far so it wasn’t executing unless `isAdmin` was `1`.

After I made these adjustments I had no issue.

---

<div class="post-metadata">

**Author:** ![djones](https://avatars.discourse-cdn.com/v4/letter/d/43a26b/32.png) [@djones](https://forum.inductiveautomation.com/u/djones)\
**Post date:** [August 31, 2020, 3:45pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/33 "2020-08-31T15:45:14Z")

</div>

I implemented #1 and no discernible change on my end. Still getting the same error in chrome.

#2 must be copy paste issue, it executes correctly at the return statement, omitted Admin == 1 to confirm.

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [August 31, 2020, 3:50pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/34 "2020-08-31T15:50:56Z")

</div>

Since you haven’t supplied the full code of the transform, I don’t know how else I can help here. The code you’ve supplied here works, so look at the code you haven’t supplied; somewhere within the transform you’re modifying the items in a way that can’t be parsed by the component.

---

<div class="post-metadata">

**Author:** ![djones](https://avatars.discourse-cdn.com/v4/letter/d/43a26b/32.png) [@djones](https://forum.inductiveautomation.com/u/djones)\
**Post date:** [August 31, 2020, 3:52pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/35 "2020-08-31T15:52:17Z")

</div>

I am running the exact code I have supplied above with the same results.

The strange thing is that the component builds just fine. I only get the error when I click on it in Chrome.

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [August 31, 2020, 4:03pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/36 "2020-08-31T16:03:51Z")

</div>

While not signed in:  
 ![Screen Shot 2020-08-31 at 8.53.04AM](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/3/43e9a228e13a237ce1231ce4c45be55a85e16a5c.png)  
After signing in:  
 ![Screen Shot 2020-08-31 at 9.02.26AM](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/6/f65e2c83c13ea7a66ec25de6b150eb8e950b735b.png)

Perhaps the issue is a result of the layout of the View?

---

<div class="post-metadata">

**Author:** ![djones](https://avatars.discourse-cdn.com/v4/letter/d/43a26b/32.png) [@djones](https://forum.inductiveautomation.com/u/djones)\
**Post date:** [August 31, 2020, 4:12pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/37 "2020-08-31T16:12:25Z")

</div>

would it matter that this is a docked header?

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [August 31, 2020, 4:14pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/38 "2020-08-31T16:14:32Z")

</div>

No, it would be the layout of the View which contains the Horizontal Menu.

---

<div class="post-metadata">

**Author:** ![djones](https://avatars.discourse-cdn.com/v4/letter/d/43a26b/32.png) [@djones](https://forum.inductiveautomation.com/u/djones)\
**Post date:** [August 31, 2020, 4:15pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/39 "2020-08-31T16:15:45Z")

</div>

It works as is on a view. It does not work in a view that is a docked header

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [August 31, 2020, 4:16pm UTC](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269/40 "2020-08-31T16:16:38Z")

</div>

Could you post a screenshot of the component in an active session?

[Previous page](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269.md?page=1)

[Next page](https://forum.inductiveautomation.com/t/perspective-horizontal-menu-component/25269.md?page=3)
