[IGN-6563]How to get view name inside the view itself

Is there any way to get the view name inside the view itself?
I can’t use page.props.primaryView because I mostly use an embedded view.

Call the prop.path property of the embedded view component, and it should produce the name:

Example:
./EmbeddedView.props.path
image

The preceding binding on a custom property produces the following result:
image

Not working you are inside the view itself. "EmbeddedView" is unknown and even works it may change by user.

Have you tried self.page.props.pageId ?

Edit:
From within a property binding, it would just be: page.props.pageId

I see what you are saying. When the view is embedded, the parent view and sub-view become indistinguishable:

1 Like

self.view.id
it puts some extra stuff after the name tho

so you’ll want something like this i guess
self.view.id.split('@')[0]

2 Likes

@victordcq

str(self.view.id).split('@')[0]

Looks good. I tried your suggestion using labels in a host view and a separate embedded view, and this was the result as viewed from Google chrome:

image

2 Likes

Where did you use this expression? I get error. Could you send me the export of the view.
I need to get it to work inside the view itself.

Its a script, not an expression

2 Likes

Keep in mind that the view id can be supplied by the caller of a popup view instead of being auto-generated.

For popups the name infront of the @ self.view.id.split('@')[0] will also be the view name.
Whats after it will be kinda different though, but whats after the @ is rarely any usefull (except maybe debugging/testing)

1 Like

Yeah, it’s a ViewInstanceId apparently, which should be consistently usable.

Ok, TIL.

Is there any way to go one level then this?
I mean the parent view path that calling embedded view.

A callout on being able to access props like view.id from an expression, it would be nice if a few more meta props were exposed in expressions directly. I see no reason that {view.id} isn’t a valid expression other than it needing to be exposed.

I run into the same problem when trying to show view parameters on a debug label, you cant bind directly to view.params, so you need to do something like an expression of now(2000) and a script transform that returns self.view.params. However then you deal with object wrappers and you need to run extra scripting to convert it (all the way down to its nested objects if deeply nested) into a regular object to interact with it. Being able to bind straight to view.params or reference {view.params} in an expression would be fantastic.

Its definitely not unheard of to make read only meta props available:

For what it’s worth, I bundled this + [IGN-6563]Retrieve Session custom props remotely together on a new internal ticket that’s pretty vague; just suggesting ‘make more things accessible’. Concrete examples (such as {view.id} above) and their use cases would be very helpful to add to that ticket.

3 Likes

Get ready for some smelly code, but here goes:

  1. Set an outbound prop on your embedded view named id with an expression of false and a script transform of self.view. This should give you the views wrapper address (something like com.inductiveautomation.perspective.gateway.script.ViewModelScriptWrapper$SafetyWrapper@b95ba6f)
  2. Create a binding with the following code:
	import time
	# Wait a second for everything to load in
	time.sleep(0.1)
		
	# Get all of the views on the current page
	views = self.view.getPage().views
	
	# Filter out this view, to make things easier
	views = filter(lambda view: view.id != self.view.id, views)
	
	# Create a function that recursively searches components with children
	def searchComponent(component):
		# If there are no children of this component, lets look for the view Id
		if len(getattr(component, "children", [])) == 0:
			# Convert the props to a dictionary so they are easier to use then a PropertyWrapper
			componentProps = dict(component.props)
			
			# Look to see if our outbound Id prop is present and the same
			if componentProps.get('params', {}).get('id') == self.view.params.id:
				# If so, return the parent views path
				return component.getView().id.split('@')[0]
		
		# If we do have children, lets recursively search through them
		else:
			for child in component.getChildren():
				viewId = searchComponent(child)
				
				# If we got a viewId, lets go ahead and jump out of the function with it
				if viewId is not None:
					return viewId
	
	
	
	# Iterate through the views to find any embedded views
	for view in views:
		# Go to the root container and get any of its children
		wrappers = view.getRootContainer().getChildren()
		
		# Go through each of the found top level wrappers and start searching!
		for wrapper in wrappers:
			viewId = searchComponent(wrapper)
			
			if viewId is not None:
				return "Parent: %s" % viewId

	return "Parent: None"

The component.getView().id.split('@')[0] will give you the path of the parent view.

Disclaimer:

  1. This doesn't work if you put the embedded view into a container, however it could probably be made recursive to go through any components with children until it finds it.
  2. This would be nice if you didn't need the outbound prop, however there is a layer between the embedded view component and the embedded view itself made of 2 safety wrappers and there is no way to get through them directly. The embedded view components safety wrapper has no children, so there is no way to get the components inside of it. And the component of the two is technically different, since they are two different components.
  3. This is smelly code and really reliant on the safety wrappers, which ironically feels unsafe

Edit: I made the script recursive for completeness

2 Likes

I am able to use page.props.primaryView when looking at the webpage.

However, when I am in designer, I can't.
Is there a way to get the view name both in designer and on the web page that I created?

In designer, page.props.pageID worked, but that doesn't work when I have my page url set to /dev1 for testing.


Never mind, I did an if statement. "Works" in both the designer and the webpage now.
Had to use self.page.props.pageId for the designer side though since my property binding lead with page.props.primaryView