Dynamically Updating a Table

I am working on a mock-up of an invoicing site, and am trying to add a row to a table based on information that is entered by the end user. Eventually it will be automatic, the information read from an attachment in an email, but for the time being I am just trying to get it to update when I click a button:

New-UDDashboard -Title 'PowerShell Universal' -Content {
    $Layout = '{"lg":[{"w":12,"h":1,"x":0,"y":16,"i":"grid-element-BlankLine1","moved":false,"static":false},{"w":12,"h":1,"x":0,"y":17,"i":"grid-element-BlankLine2","moved":false,"static":false},{"w":2,"h":2,"x":0,"y":0,"i":"grid-element-newInvoice","moved":false,"static":false},{"w":12,"h":14,"x":0,"y":2,"i":"grid-element-dynTable","moved":false,"static":false}]}'

    New-UDGridLayout -Content {
        New-UDTypography -Id "BlankLine1" -Text ''
        New-UDTypography -Id "BlankLine2" -Text ''

        $tableData = @(
            @{Status = 'Pending';Number = '121148';Vendor = 'Morales';Date = "04/15/2022";Amount = "1241.60";Assigned = "Jennifer";Notes = "Waiting on completion of i90 work"}
        )
        
        New-UDButton -Id "newInvoice" -Text "Add New Invoice" -OnClick {
            $tableData += [PSCustomObject]@{Status = 'Paid';Number = '12345';Vendor = 'Mutually Human';Date = "05/02/2022";Amount = "86753.09";Assigned = "Jennifer";Notes = "Paid"}
            foreach ($element in $tableData) {
                Show-UDToast -Message $element.Status -Duration 3000
            }
            Sync-UDElement -Id "dynTable"
        }

        $aColumns = @(
            New-UDTableColumn -Property Pay -Title "Pay" -Width 180 -Truncate -Render {
                New-UDButton -Id "btn$($EventData.Number)" -Text "Pay Invoice"
            }
            New-UDTableColumn -Property Status -Title "Status"
            New-UDTableColumn -Property Number -Title "Number"
            New-UDTableColumn -Property Vendor -Title "Vendor"
            New-UDTableColumn -Property Date -Title "Date"
            New-UDTableColumn -Property Amount -Title "Amount"
            New-UDTableColumn -Property Assigned -Title "Assigned"
            New-UDTableColumn -Property Notes -Title "Notes"
        )

        New-UDDynamic -Id "dynTable" -Content {
            New-UDTable -Data $tableData -Columns $aColumns
        }
    } -Layout $Layout
}

I’ve tried wrapping both the button and the table in a UDDynamic, but did not think I had to do that. Also, I can see, with the foreach loop, that the second row is being added to the collection, it is just the table element not refreshing. Hopefully I am just missing something stupid simple here.

Product: PowerShell Universal
Version: 2.10.2

Try just putting this part in the Dynamic element above the table

$tableData += [PSCustomObject]@{Status = 'Paid';Number = '12345';Vendor = 'Mutually Human';Date = "05/02/2022";Amount = "86753.09";Assigned = "Jennifer";Notes = "Paid"}
            foreach ($element in $tableData) {
                Show-UDToast -Message $element.Status -Duration 3000
            }

Thanks for the suggestion. I did try to wrap the button (adding to the $tableData collection has to occur off the button click) to a dynamic block. I see the same behavior, though - the new row is added to $tableData but the table element itself is not refreshed to show the new row count.

Don’t wrap the while button, just wrap the data processing.

Sorry, I must be thick this morning; not understanding what you mean. If I put the data processing into the dynamic, above the table, it is just going to process on first pass, instead of when the button is clicked.

        New-UDDynamic -Id "dynTable" -Content {
            $tableData += [PSCustomObject]@{Status = 'Paid';Number = '12345';Vendor = 'Mutually Human';Date = "05/02/2022";Amount = "86753.09";Assigned = "Jennifer";Notes = "Paid"}           
            New-UDTable -Data $tableData -Columns $aColumns
        }

Doing it like this, on page load both rows are added to the table.

As an aside, I also tried it this way:

New-UDDashboard -Title 'PowerShell Universal' -Content {
    $Layout = '{"lg":[{"w":12,"h":1,"x":0,"y":2,"i":"grid-element-BlankLine1","moved":false,"static":false},{"w":12,"h":1,"x":0,"y":3,"i":"grid-element-BlankLine2","moved":false,"static":false},{"w":2,"h":2,"x":0,"y":0,"i":"grid-element-newInvoice","moved":false,"static":false},{"w":12,"h":7,"x":0,"y":4,"i":"grid-element-myTable","moved":false,"static":false}]}'

    New-UDGridLayout -Content {
        New-UDTypography -Id "BlankLine1" -Text ''
        New-UDTypography -Id "BlankLine2" -Text ''

        $aColumns = @(
            New-UDTableColumn -Property Pay -Title "Pay" -Width 180 -Truncate -Render {
                New-UDButton -Id "btn$($EventData.Number)" -Text "Pay Invoice" -OnClick {
                    Sync-UDElement -Id "myTable"
                }
            }
            New-UDTableColumn -Property Status -Title "Status"
            New-UDTableColumn -Property Number -Title "Number"
            New-UDTableColumn -Property Vendor -Title "Vendor"
            New-UDTableColumn -Property Date -Title "Date"
            New-UDTableColumn -Property Amount -Title "Amount"
            New-UDTableColumn -Property Assigned -Title "Assigned"
            New-UDTableColumn -Property Notes -Title "Notes"
        )
        
        $tableData = @(
            @{Status = 'Pending';Number = '121148';Vendor = 'Morales';Date = "04/15/2022";Amount = "1241.60";Assigned = "Jennifer";Notes = "Waiting on completion of i90 work"}
        )
        New-UDDynamic -Id "myTable" -Content {
            New-UDTable -Data $tableData -Columns $aColumns
        } -LoadingComponent {
            "Loading"
        }

        New-UDButton -Id "newInvoice" -Text "Add New Invoice" -OnClick {
            $aParams = [ordered]@{
                Status = 'Paid'
                Number = '12345'
                Vendor = 'Mutually Human'
                Date = "05/02/2022"
                Amount = "86753.09"
                Assigned = "Jennifer"
                Notes = "Paid"
            }

            $tableData += New-Object PSObject -Property $aParams

            foreach ($row in $tableData) {
                Show-UDToast -Message $row.Number -Duration 3000
            }
            Sync-UDElement -Id "myTable"
        }
    } -Layout $Layout -Design
}

I confirm the $tableData has the new row, and I actually see the LoadingComponent flash on the table, which I would think means it is being refreshed. But the new row does not show up on the table itself.

You probably need to use a session variable. This worked for me.

New-UDDashboard -Title 'PowerShell Universal' -Content {
    $Layout = '{"lg":[{"w":12,"h":1,"x":0,"y":2,"i":"grid-element-BlankLine1","moved":false,"static":false},{"w":12,"h":1,"x":0,"y":3,"i":"grid-element-BlankLine2","moved":false,"static":false},{"w":2,"h":2,"x":0,"y":0,"i":"grid-element-newInvoice","moved":false,"static":false},{"w":12,"h":7,"x":0,"y":4,"i":"grid-element-myTable","moved":false,"static":false}]}'

    New-UDGridLayout -Content {
        New-UDTypography -Id "BlankLine1" -Text ''
        New-UDTypography -Id "BlankLine2" -Text ''

        $aColumns = @(
            New-UDTableColumn -Property Pay -Title "Pay" -Width 180 -Truncate -Render {
                New-UDButton -Id "btn$($EventData.Number)" -Text "Pay Invoice" -OnClick {
                    Sync-UDElement -Id "myTable"
                }
            }
            New-UDTableColumn -Property Status -Title "Status"
            New-UDTableColumn -Property Number -Title "Number"
            New-UDTableColumn -Property Vendor -Title "Vendor"
            New-UDTableColumn -Property Date -Title "Date"
            New-UDTableColumn -Property Amount -Title "Amount"
            New-UDTableColumn -Property Assigned -Title "Assigned"
            New-UDTableColumn -Property Notes -Title "Notes"
        )
        
        $session:tableData = ,@(
            @{Status = 'Pending';Number = '121148';Vendor = 'Morales';Date = "04/15/2022";Amount = "1241.60";Assigned = "Jennifer";Notes = "Waiting on completion of i90 work"}
        )
        New-UDDynamic -Id "myTable" -Content {
            New-UDTable -Data $session:tableData -Columns $aColumns
        } -LoadingComponent {
            "Loading"
        }

        New-UDButton -Id "newInvoice" -Text "Add New Invoice" -OnClick {
            $aParams = [ordered]@{
                Status = 'Paid'
                Number = '12345'
                Vendor = 'Mutually Human'
                Date = "05/02/2022"
                Amount = "86753.09"
                Assigned = "Jennifer"
                Notes = "Paid"
            }

            $session:tableData += New-Object PSObject -Property $aParams

            foreach ($row in $session:tableData) {
                Show-UDToast -Message $row.Number -Duration 3000
            }
            Sync-UDElement -Id "myTable"
        }
    } -Layout $Layout -Design
}

Thanks @adam , I missed the whole needing a session variable piece. That works perfectly.

Ok, I thought I had it worked out, but found something new. Here is the (mostly) working code for this page:

function update {
    [CmdLetBinding()]
    Param (
        [Parameter(Mandatory, Position=1)]
            [string] $POStatus,
        [Parameter(Mandatory, Position=2)]
            [string] $Number,
        [Parameter(Mandatory, Position=3)]
            [string] $POVendor,
        [Parameter(Mandatory, Position=4)]
            [string] $Date,
        [Parameter(Mandatory, Position=5)]
            [string] $Amount,
        [Parameter(Mandatory, Position=6)]
            [string] $POAssigned,
        [Parameter(Mandatory, Position=7)]
            [string] $Notes
    )

    $aParams = [ordered]@{
        Status = $POStatus
        Number = $Number
        Vendor = $POVendor
        Date = $Date
        Amount = $Amount
        Assigned = $POAssigned
        Notes = $Notes
    }

    $session:tableData += New-Object PSObject -Property $aParams
}

$aVendors = @("Mutually Human","Wayland PC","Sunrise Inc.","E-Tech Housing","OpinionPoll.com","Quest Diagnostics","Morales Industries")

New-UDDashboard -Title 'PowerShell Universal' -Content {
    $Layout = '{"lg":[{"w":12,"h":1,"x":0,"y":2,"i":"grid-element-BlankLine1","moved":false,"static":false},{"w":12,"h":1,"x":0,"y":10,"i":"grid-element-BlankLine2","moved":false,"static":false},{"w":12,"h":7,"x":0,"y":3,"i":"grid-element-myTable","moved":false,"static":false},{"w":2,"h":2,"x":0,"y":0,"i":"grid-element-newInvoice","moved":false,"static":false}]}'

    New-UDGridLayout -Content {
        New-UDTypography -Id "BlankLine1" -Text ''
        New-UDTypography -Id "BlankLine2" -Text ''

        $aColumns = @(
            New-UDTableColumn -Property Pay -Title "Pay" -Width 180 -Truncate -Render {
                New-UDButton -Id "btn$($EventData.Number)" -Text "Pay Invoice" -OnClick {
                    Sync-UDElement -Id "myTable"
                }
            }
            New-UDTableColumn -Property Status -Title "Status"
            New-UDTableColumn -Property Number -Title "Number"
            New-UDTableColumn -Property Vendor -Title "Vendor"
            New-UDTableColumn -Property Date -Title "Date"
            New-UDTableColumn -Property Amount -Title "Amount"
            New-UDTableColumn -Property Assigned -Title "Assigned"
            New-UDTableColumn -Property Notes -Title "Notes"
        )
        
        $session:tableData = ,@(
            @{Status = 'Pending';Number = '121148';Vendor = 'Morales';Date = "04/15/2022";Amount = "1241.60";Assigned = "Jennifer";Notes = "Waiting on completion of i90 work"}
        )
        
        New-UDDynamic -Id "myTable" -Content {
            New-UDTable -Data $session:tableData -Columns $aColumns
        } -LoadingComponent {
            "Loading"
        }

        New-UDButton -Id "newInvoice" -Text "Add New Invoice" -OnClick {
            Show-UDModal -Content {
                New-UDGrid -Container -Content {
                    New-UDGrid -Item -MediumSize 4 -Content {
                        New-UDTypography -Text ""
                    }

                    New-UDGrid -Item -MediumSize 4 -Content {
                        New-UDTypography -Text "Enter New Payment" -Style @{
                            "font-size" = "24px"
                        }
                    }

                    New-UDGrid -Item -MediumSize 4 -Content {
                        New-UDTypography -Text ""
                    }

                    foreach ($a in 1..2) {
                        New-UDGrid -Item -MediumSize 12 -Content {
                            New-UDTypography -Text " " -Style @{
                                whiteSpace = 'pre'
                            }
                        }
                    }

                    New-UDGrid -Item -MediumSize 4 -Content {
                        New-UDSelect -Id "statusSelect" -Option {
                            New-UDSelectOption -Name 'Payment Status' -Value 1
                            New-UDSelectOption -Name 'Pending' -Value 2
                            New-UDSelectOption -Name 'Paid' -Value 3
                            New-UDSelectOption -Name 'In Dispute' -Value 4
                        } -DefaultValue 1
                    }

                    New-UDGrid -Item -MediumSize 4 -Content {
                        New-UDTextbox -id "PONumber" -Label "PO Number"
                    }

                    New-UDGrid -Item -MediumSize 4 -Content {
                        New-UDSelect -Id "vendorSelect" -Option {
                            New-UDSelectOption -Name 'Select Vendor' -Value 7
                
                            foreach ($company in $aVendors) {
                                New-UDSelectOption -Name "$($company)" -Value ($aVendors.IndexOf($company))
                            }
                        } -DefaultValue 7
                    }

                    foreach ($a in 1..2) {
                        New-UDGrid -Item -MediumSize 12 -Content {
                            New-UDTypography -Text " " -Style @{
                                whiteSpace = 'pre'
                            }
                        }
                    }

                    New-UDGrid -Item -MediumSize 4 -Content {
                        New-UDTextbox -id "PODate" -Label "Date"
                    }

                    New-UDGrid -Item -MediumSize 4 -Content {
                        New-UDTextbox -id "POAmount" -Label "Amount"
                    }

                    New-UDGrid -Item -MediumSize 4 -Content {
                        New-UDSelect -Id "assignSelect" -Option {
                            New-UDSelectOption -Name 'Select Assignee' -Value 3
                            $aUsers = @("Jennifer", "Samantha")

                            foreach ($user in $aUsers) {
                                New-UDSelectOption -Name "$($user)" -Value ($aUsers.IndexOf($user))
                            }
                        } -DefaultValue 3
                    }

                    foreach ($a in 1..2) {
                        New-UDGrid -Item -MediumSize 12 -Content {
                            New-UDTypography -Text " " -Style @{
                                whiteSpace = 'pre'
                            }
                        }
                    }

                    New-UDGrid -Item -MediumSize 8 -Content {
                        New-UDTextbox -id "PONotes" -Label "Notes" -FullWidth
                    }

                    New-UDGrid -Item -MediumSize 4 -Content {
                        New-UDButton -Id "submitPO" -Text "Submit to System" -OnClick {
                            $status = (Get-UDElement -Id "statusSelect").value
                            $PONumber = (Get-UDElement -Id "PONumber").value
                            $vendor = (Get-UDElement -Id "vendorSelect").value
                            $PODate = (Get-UDElement -Id "PODate").value
                            $POAmount = (Get-UDElement -Id "POAmount").value
                            $assigned = (Get-UDElement -Id "assignSelect").value
                            $PONotes = (Get-UDElement -Id "PONotes").value

                            update -POStatus $status -Number $PONumber -POVendor $vendor -Date $PODate -Amount $POAmount -POAssigned $assigned -Notes $PONotes
                            Start-Sleep 1
                            Hide-UDModal
                            Start-Sleep -Milliseconds 100
                            Show-UDModal
                            Hide-UDModal
                            
                        }
                    }
                }
            }

            Sync-UDElement -Id "myTable"
        }
    } -Layout $Layout
}

I moved the updating of the $tableData to a function. When the user clicks on the Add New Invoice button, it brings up a Modal with the fields they need to fill out. Once filled out and the user clicks the Submit to System button, my intent it to grab all the necessary fields, call the function to add the new row to $tableData, then close the Modal and update the table. Unfortunately, on first click it does not update anything (although it does call the function and update the $tableData collection).

However, if I click the Add New Invoice button again and bring the (empty) Modal back up, the new row populates.

GIF

Is there some reason I am having to open and close the Modal a second time?