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
The preceding binding on a custom property produces the following result:
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:
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]
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:
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
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)
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.
Get ready for some smelly code, but here goes:
- Set an outbound prop on your embedded view named
id
with an expression offalse
and a script transform ofself.view
. This should give you the views wrapper address (something likecom.inductiveautomation.perspective.gateway.script.ViewModelScriptWrapper$SafetyWrapper@b95ba6f
) - 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:
- 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.
- 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.
- This is smelly code and really reliant on the safety wrappers, which ironically feels unsafe
Edit: I made the script recursive for completeness
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