Variables, New-UDDynamic and Environments

So, I’m using the dashboard below for learning some PSU behaviors. I have a copy running in a Persistent and non-Persistent environment.

Below is a hopefully not TOO confusing spreadsheet of the behaviors…
Findings

Undocumented are interactions between a page in a normal window, and an incognito window (it gets messier).

End result is: Variables on pages may not be the expected results to the user interacting with it. Especially with a persistence in the environment.

Would there be any way to create a more “instanced” scope variable?

For example $Instance:Variable - Behavior would be it’s attached to the user, like Session, however it’s also only available to the currently viewed page. That way, multiple tabs of the same pages would have the proper variables.

Currently having some grief because of these behaviors in my real-world dashboard

$Pages = @()

$Pages += New-UDPage -Name 'Debug' -Content {
    New-UDForm -Content {
        New-UDTextbox -Id 'txtID' -Label 'ID'
    } -OnValidate {
        If ($Eventdata.txtID -eq '') {
            New-UDFormValidationResult -ValidationError "ID can't be blank"
        }
        else {
            New-UDFormValidationResult -Valid
        }
    } -OnSubmit {
        Invoke-UDRedirect -Url "/Debug/$($EventData.txtID)"
    }
} 

$Pages += New-UDPage -Name 'DebugID' -Url '/Debug/:id' -Content {
    New-UDDynamic -id 'dynFirstButtonSet' -Content {
        $tempID = $ID
        $Script:ID = $ID
        $Global:ID = $ID
        $Session:ID = $ID
    }
    New-UDDynamic -id 'dynSecondButtonSet' -Content {
        $tempID2 = $ID
        $Script:ID2 = $ID
        $Global:ID2 = $ID
        $Session:ID2 = $ID
    } -AutoRefresh -AutoRefreshInterval 5
    New-UDDynamic -Content {
        $tempID3 = $ID
        $Script:ID3 = $ID
        $Global:ID3 = $ID
        $Session:ID3 = $ID
    }
    New-UDDynamic -Content {
        $tempID4 = $ID
        $Script:ID4 = $ID
        $Global:ID4 = $ID
        $Session:ID4 = $ID
    } -AutoRefresh -AutoRefreshInterval 5
    New-UDGrid -Container -Children {
        New-UDButton -Text "Direct" -OnClick {
            Show-UDToast -Message $ID
        }
        New-UDButton -Text "tempID" -OnClick {
            Show-UDToast -Message $tempID
        }
        New-UDButton -Text "Script" -OnClick {
            Show-UDToast -Message $Script:ID
        }
        New-UDButton -Text "Global" -OnClick {
            Show-UDToast -Message $Global:ID
        }
        New-UDButton -Text "Session" -OnClick {
            Show-UDToast -Message $Session:ID
        }
    }
    New-UDGrid -Container -Children {
        New-UDButton -Text "Direct2" -OnClick {
            Show-UDToast -Message $ID
        }
        New-UDButton -Text "tempID2" -OnClick {
            Show-UDToast -Message $tempID2
        }
        New-UDButton -Text "Script2" -OnClick {
            Show-UDToast -Message $Script:ID2
        }
        New-UDButton -Text "Global2" -OnClick {
            Show-UDToast -Message $Global:ID2
        }
        New-UDButton -Text "Session2" -OnClick {
            Show-UDToast -Message $Session:ID2
        }
    }
    New-UDGrid -Container -Children {
        New-UDButton -Text "Direct3" -OnClick {
            Show-UDToast -Message $ID
        }
        New-UDButton -Text "tempID3" -OnClick {
            Show-UDToast -Message $tempID3
        }
        New-UDButton -Text "Script3" -OnClick {
            Show-UDToast -Message $Script:ID3
        }
        New-UDButton -Text "Global3" -OnClick {
            Show-UDToast -Message $Global:ID3
        }
        New-UDButton -Text "Session3" -OnClick {
            Show-UDToast -Message $Session:ID3
        }
    }
    New-UDGrid -Container -Children {
        New-UDButton -Text "Direct4" -OnClick {
            Show-UDToast -Message $ID
        }
        New-UDButton -Text "tempID4" -OnClick {
            Show-UDToast -Message $tempID4
        }
        New-UDButton -Text "Script4" -OnClick {
            Show-UDToast -Message $Script:ID4
        }
        New-UDButton -Text "Global4" -OnClick {
            Show-UDToast -Message $Global:ID4
        }
        New-UDButton -Text "Session4" -OnClick {
            Show-UDToast -Message $Session:ID4
        }
    }
    
}
New-UDDashboard -Title 'PowerShell Universal' -Pages $Pages
Product: PowerShell Universal
Version: 3.2.3

Thanks Jori, this could probably help with the issue I’m facing on my thread :https://forums.ironmansoftware.com/t/eventdata-once-sporadicly-works-then-empty/7738

I will try your code as well next week to see if it relates somehow…
Best regards
Don

I would suggest avoiding the use of $temp, global and session variable scopes for dashboards because of how runspaces are reused.

The persistent runspaces provide no guarantees that the runspace will be reused by the same user. Like you’ve seen, weird things can happen when viewing two pages at once since those variables were set during different executions. It will get even more weird the more the users connect. With non-persistent runspaces, the runspace state is reset every time the runspace is reused. I’m really surprised the global scope continues to work in some circumstances when your environment is configured like this.

Session variables are consistent but only for the session and not for the page in general. I do think that some sort of page-based variable scope may be useful for this reason.

I know some users that will create variables that are named specific to the page they are using:

$Session:Page1_Id = "Something" 

For a dynamic page like your example, you may want to consider using a different type of object that can store dynamic keys.

New-UDPage -Url /test/:id -Content {
    if (-not $Session:Data)
    { 
         $Session:Data = @{} 
    }

    $Session:Data[$Id] = "Some value"
}

Hi Adam,

Thanks for that recommendation. Turning persistence off and using a synchronized hashtable is working.

A persistent runspace under these conditions doesn’t seem feasible without a $Page: scope though. I’ll open up an enhancement request :slight_smile:

3 Likes