Perspective/View/Params - disappear

If I uncheck Persistent for a parameter I’ve created it will have disappeared once I close then re-open the same view in designer. Every instance utilizing the parameter works fine on a client until i run the view in preview mode with designer.

ie: imageName parameter no longer appears to exist but my insert query that uses the variable fileName executes fine until I preview the view.

I feel like you're missing some important screenshots which would help explain what you're seeing. Let's start with a few assumptions

  1. You've created a param named imageName for the view and it has a value, AND you've set it to no longer be persistent.
  2. you have a binding which uses imageName in some way in place and it is working. If you look at the binding, you'll see that imageName is returning a value.
  3. If you enter Preview mode right now, you'll see that everything is fine.

Now comes the trouble part: you close the View, or reach the View in an active session.

Due to toggling off the Persistent property, the param is not saved, which means bindings which use it will fail to locate the property.

This part has me a little confused though. Any "client" (session) which makes use a a non-persistent property will fail when it finds that property is not in place, except for one scenario: the param is created at runtime by some other script. If the param is created somewhere else

# perhaps something like this
self.view.params.imageName = 'something.png'

then references to the property will work because it now exists.

Have you tried this? I know it sounds absurd but this error will only show up if i run the screen in preview mode, then clients will fail following after that point:

I'm creating this parameter and others by clicking +AddViewParameter.

If there are any other screenshots or information you think would be helpful let me know.

Is there a specific reason you’re removing the persistence of this param? While we allow for toggling the persistence, it should really be left “on” if the property is going to be used in bindings.

Here was my experience after running through steps similar to your setup:

  1. Place imageName param (doesn’t have to be a param - it could be any property).
  2. Bind some property to self.view.params.imageName.
  3. Save project.
  4. Open Session to View
  5. Result: binding is session is still working.
  6. Toggle persistence to “off”.
  7. Result: binding is session is still working.
  8. Enter Preview Mode.
  9. Result: binding is session is still working.
  10. Save Project.
  11. Result: binding in session is no longer working, as the persistence setting has now been saved to the Session.

When I mentioned “created somewhere else” I meant like a script - like I provided an example of.

Could you screenshot the Query along with however you’re invoking it and how it’s getting fileName? A better option would be to supply me with the view.json file for the View you’re using. If you’re hesitant to provide that file on the forum, you could always send it to me through a private message.

Close the view after this step. Upon re-opening your param still exists? Mine are disappearing.

I'll post these shortly.

def runAction(self, event):
"""
This event is fired when the 'action' of the component occurs.

Arguments:
	self: A reference to the component that is invoking this function.
	event: An empty event object.
"""
# Write your script here
fileName = self.view.params.imageName

filePath = 'webserver/webapps/main/image/' + (fileName)	
imageBlob = system.file.readFileAsBytes(filePath)	


system.db.runPrepUpdate("INSERT INTO table (image) VALUES (?)", [imageBlob], 'DB')

def runAction(self, event):
“”"
Fired after the gateway has received a file upload.

Arguments:
	self: A reference to the component that is invoking this function.
	event: An object with the following attributes:
		file: An object with the following attributes:
			name (str): The name of the uploaded file.
			size (int): The size (in bytes) of the file that was uploaded.
"""

filePath = 'webserver/webapps/main/image/'
name = event.file.name
self.view.params.imageName = name

event.file.copyTo(filePath + name)

Closing the View commits the changes to the View (though they aren't "pushed" or saved to the Gateway yet), so when you re-open, the param will not be there.

Modifying my steps to close the View as the next step after toggling Persistence to "off" did not modify the behavior of my sessions in any way. I'm beginning to think that our disconnect is stemming from phrasing you used in the original post:

I understood this to mean that you had running Perspective Sessions ("clients") which were working up until you entered Preview Mode in the Designer - at which point those remote sessions ceased functioning. If you meant that the Designer was working up until you entered Preview Mode, well then yes, this is all expected.

Once you close the View, the changes you've made so far are committed locally in the Designer - this includes your toggling of the Persistence property to "off", which means that when you re-open the View it has your committed changes, which means the param is missing. Everything will look fine, but once it attempts to read the param which no longer exists, your script will fail with the Exceptions you are seeing in your screenshot.

As I suggested before, the easy solution to this is to leave the property as having Persistent set to "on".

Hi, I’ve recently stumbled across this thread after spending a good hour and half trying to figure out why my views kept breaking.

I was under the impression that the ‘Persistent’ property governed persistence of values, not keys (as noted here ). After searching through the docs, I was unable to find any documentation stating that the behavior of the “Persistence” property for View Params was any different.

As a user, I’ve been under the impression that “Persistence for properties should be on, unless it’s used in a binding”. Having View Params (which I think are just special cases of properties) buck this trend is extremely confusing - especially given that I can’t find any easily-accessible documentation stating this exception.

1 Like

I took a quick look at the view.json for the view where I first ran into this. Interestingly, setting “persistent” to False doesn’t delete the param entirely - it just seems to stop the Designer & Session from being aware of it entirely.

It seems there’s a disconnect regarding whether the ‘persistent’ preference should apply to parameter values as the documentation and the designer explainer pop-up suggest or parameter instances themselves, as @osolorzano suggests in this thread.

Clearly as of now, it seems the latter is the case, but i’m strongly in favor of the former, and what i imagine was the original intent - no sense having properties just disappear, especially if they don’t really disappear in the JSON (which would break things anyway), but just become invisible in the designer.

And like @tyrel.parker suggests - these parameters are often modified for testing, and so should not retain their ‘test’ initial values just because someone forgets to clear the test values, regardless if they will likely be immediately overwritten by bindings at run time. I’ve had an embarrassing situation where comms were lost, and on view reloads across the plant, the obviously very-wrong ‘test’ initial values were displayed. Thus my desire to make all my bound property/view parameter values non-persistent.

1 Like

The real answer here is that the concept of any property "instance" (including parameters) with no value is a meaningless concept, at least in the JSON-based property model that powers Perspective.

Thought experiment. Consider the following JSON document:

{
    "foo": "bar",
    "baz": "qux"
}

Now, show me that document where "baz" has no value.

... what i imagine was the original intent ...

This is probably the root of the misunderstanding. The original intent of the "persistent" property has a very narrow (and different) meaning than what you're trying to use it for. The intent was to ensure that values generated by bindings that execute in the Designer don't get saved into the view. The purpose for this is two-fold:

  1. So that views don't start up with initial values that represent the state that the process was in when last running in the designer. This would cause a brief flash of incorrect values.
  2. So that bindings that generate very large objects/arrays/datasets don't have their values stored as configuration with the component, causing the saved view size to be bloated with information that will be re-generated when the view starts up anyhow.

With all that said, I think you have a valid use case for your parameter value / test value concept, it's just that's not what "persistent" means. Perhaps we need some new feature concept for a forced initial value? You might use a binding to an expression that generates a static value for this in the meantime.

1 Like

Thank you! As always it's useful to understand different perspectives. I think I've wrapped my head around it with your help.

The value of this property will not be saved with the view

  1. current implementation (i'd call it "brutalist", but I'm no dev, so please don't take offense)

    • effectively delete the property instance
      • because valid JSON object instance requires key-value pair
    • retain binding information/references to the now undefined property
      • so they still work/the instance can be regenerated
      • thus the "bindings only" nature you refer to?
  2. alternative (literal?) interpretation

    • Read/cache the pre-existing parameter instance when re-saving
      • (literally overwrite everything but the non-persistent parameters)
      • effectively "read only" toggle per-property
  3. user-friendly (but not literally correct/not as flexible).

    • save as default "value" or null
      • similar to "forced initial value" you refer to?

I'd agree/argue sure #1 is technically correct as implemented ("don't save" = effectively delete if generating JSON from scratch), but it's not great from UX perspective because the property disappears (albeit temporarily only for bound properties). Documentation doesn't mention "bound-only", nor does designer restrict action to bound properties, thus the dilemma we find ourselves in.

I'd also agree with/argue that my/our desired (and a useful) use case (and the documentation) is more or less aligned to options 2 or 3, while avoiding surprise deletions altogether:

to ensure that values generated by bindings that execute in the Designer don’t get saved into the view

Though I/we may now more properly understand the underlying cause, the issue remains:

  • "persistent" documentation/designer pop-up description doesn't match behavior/implementation (or bound-only intent)
    • effectively deletes unbound instances
    • hides (deletes) bound instances temporarily before recreating thanks to binding info (JSON "propConfig"?) of bind-referenced property

I was bitten by this misunderstanding of persistent properties too. As was pointed out by @hunterdg neither the designer tooltip nor the documentation make it clear how persistent properties behave, nor how they are intended to be used.

Can the designer tooltip and documentation be updated to make this clearer?

You might use a binding to an expression that generates a static value for this in the meantime.

It seems like a reasonable approach. I tested a binding like this:

if({session.props.device.type}='designer', 'testValue', 'realValue')

This had the desired effect for a property. The binding approach works with properties, but does not work with parameters. Attempting to set a binding on a parameter triggers the error "Cannot configure bindings on input parameters."

Are there any other workarounds for having designer-only test values for parameters? If not we will have to set a parameter value for testing, then change it before saving. That can be tough when there are several parameters.

1 Like

I too assumed the ‘persistent’ property would be most useful when applied to view parameters, however I believe the intent is to toggle off the ‘persistent’ preference on the properties that reference your view parameters, though I’ve only arrived at this realization as a result of this conversation. This presumably allows saving test view parameter values to the project, while being sure to ignore them at runtime, as the ‘bound’ property value literally doesn’t exist in the JSON.

For what it’s worth, only input parameters are unable to be bound. As a workaround, you can change parameters to read/write (input/output) by clicking the arrow to the right of the parameter. This will allow static expression bindings as @Carl.Gould mentions to be attached and thus they will no longer be subject to the permanent deletion by the ‘persistent’ preference implementation as it exists today (values won’t be saved, but the binding expression will).

I’d suggest this is most definitely only a workaround, and could potentially cause problems if a now read/write parameter that should be input/read-only were somehow/accidentally exposed in a writable component.

It does seem to make intuitive sense (to me anyway) that input view parameters, while not able to be bound, should have a method of saving a default or null value (or modifying value persistence), thus allowing us to modify them at will in the designer (for test purposes) without having to revert them or worry that the test values might get saved to the view. This seems more initially accessible than finding/changing the ‘persistent’ preference on all the properties that reference the view params (multiple bound properties reference single view parameters in my world). This was the root of my misunderstanding.

Here’s a thought - perhaps all bound properties should be non-persistent by default and input/in-out view parameters should always be persistent? This would negate the issue of having to worry about view param initial values and force designers to plan for "default’ initial conditions if they don’t want errors in cases where bindings fail, as opposed to designing to avoid seeing test/initial values when bindings fail? Of course this would break existing installs that rely on seeing initial values in error conditions.