diff --git a/docs/Tutorials/Elements/Table.md b/docs/Tutorials/Elements/Table.md index 91cc3a77..6499402c 100644 --- a/docs/Tutorials/Elements/Table.md +++ b/docs/Tutorials/Elements/Table.md @@ -268,3 +268,78 @@ $table | Add-PodeWebTableButton -Name 'Excel' -Icon Database -ScriptBlock { New-PodeWebContainer -Content $table ``` + +## MultiSelect + +You can allow multiple rows to be selected in a table by passing the `-MultiSelect` switch to [`New-PodeWebTable`](../../../Functions/Elements/New-PodeWebTable). This adds a checkbox column to each row. + +!!! important + `-MultiSelect` requires `-DataColumn` to be set. The value of that column for each selected row is what gets passed to button scriptblocks as the selection. + +```powershell +$table = New-PodeWebTable -Name 'Services' -DataColumn Name -MultiSelect -ScriptBlock { + foreach ($svc in (Get-Service)) { + [ordered]@{ + Name = $svc.Name + Status = "$($svc.Status)" + StartType = "$($svc.StartType)" + } + } +} + +New-PodeWebContainer -Content $table +``` + +### Acting on a Selection + +When combined with [`Add-PodeWebTableButton`](../../../Functions/Elements/Add-PodeWebTableButton), the `-DataColumn` values of all checked rows are available in the button's scriptblock via `$WebEvent.Data['Selection']` as a comma-separated string. + +```powershell +$table = New-PodeWebTable -Name 'Services' -DataColumn Name -MultiSelect -ScriptBlock { + foreach ($svc in (Get-Service)) { + [ordered]@{ + Name = $svc.Name + Status = "$($svc.Status)" + StartType = "$($svc.StartType)" + } + } +} + +$table | Add-PodeWebTableButton -Name 'StopSelected' -DisplayName 'Stop Selected' -Icon 'Stop-Circle' -WithText -ScriptBlock { + $selected = $WebEvent.Data['Selection'] -split ',' + if ($selected.Length -eq 0) { + Show-PodeWebToast -Message 'No services selected' -Title 'StopSelected' + } + else { + foreach ($svc in $selected) { + Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue + } + Show-PodeWebToast -Message "Stopped $($selected.Count) service(s)" -Title 'Done' + Sync-PodeWebTable -Name 'Services' + } +} + +New-PodeWebContainer -Content $table +``` + +If you want to confirm the selection before acting on it, you can open a Modal from the button's scriptblock and pass the selected values through using [`Update-PodeWebTextbox`](../../../Functions/Actions/Update-PodeWebTextbox): + +```powershell +$table | Add-PodeWebTableButton -Name 'StopSelected' -DisplayName 'Stop Selected' -Icon 'Stop-Circle' -WithText -ScriptBlock { + $selected = $WebEvent.Data['Selection'] -split ',' + Show-PodeWebModal -Name 'ConfirmStop' -Actions @( + Update-PodeWebTextbox -Name 'SelectedServices' -Value ($selected -join "`n") + ) +} + +New-PodeWebModal -Name 'ConfirmStop' -DisplayName 'Stop Selected Services' -AsForm -Content @( + New-PodeWebTextbox -Name 'SelectedServices' -DisplayName 'Selected Services' -Multiline -ReadOnly +) -ScriptBlock { + $names = ($WebEvent.Data['SelectedServices'] -split "`n") | Where-Object { ![string]::IsNullOrWhiteSpace($_) } + foreach ($svc in $names) { + Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue + } + Show-PodeWebToast -Message "Stopped $($names.Count) service(s)" -Title 'Done' + Hide-PodeWebModal +} +``` diff --git a/examples/tables.ps1 b/examples/tables.ps1 index 16caa5a8..d375d0ca 100644 --- a/examples/tables.ps1 +++ b/examples/tables.ps1 @@ -57,5 +57,63 @@ Start-PodeServer -Threads 2 { ) ) - Add-PodeWebPage -Name 'Home' -Path '/' -HomePage -Content $card1, $card2 -Title 'Tables' + $multiTable = New-PodeWebTable ` + -Name 'MultiSelect' ` + -PageSize 4 ` + -Paginate ` + -Filter ` + -SimpleFilter ` + -Compact ` + -DataColumn 'ID' ` + -MultiSelect ` + -ScriptBlock { + $allProcesses = @(Get-Process | ForEach-Object { + [ordered]@{ + Name = $_.Name + ID = $_.Id + WorkingSet = $_.WorkingSet + CPU = $_.CPU + } + }) + + $totalCount = $allProcesses.Count + $pageIndex = [int]$WebEvent.Data.PageIndex + $pageSize = [int]$WebEvent.Data.PageSize + $processes = $allProcesses[(($pageIndex - 1) * $pageSize) .. (($pageIndex * $pageSize) - 1)] + + $processes | Update-PodeWebTable -Name $ElementData.Name -PageIndex $pageIndex -TotalItemCount $totalCount + } ` + -Columns @( + Initialize-PodeWebTableColumn -Key 'Name' + Initialize-PodeWebTableColumn -Key 'ID' + Initialize-PodeWebTableColumn -Key 'WorkingSet' -Name 'Memory' + Initialize-PodeWebTableColumn -Key 'CPU' -Hide + ) + + $multiTable | Add-PodeWebTableButton -Name 'StopSelected' -DisplayName 'Stop Selected' -Icon 'delete' -WithText -ScriptBlock { + $selected = $WebEvent.Data['Selection'] -split ',' + if ($selected.Length -eq 0) { + Show-PodeWebToast -Message 'No processes selected' -Title 'MultiSelect' -Duration 3000 + } + else { + Show-PodeWebModal -Name 'StopSelected' -Actions @( + Update-PodeWebTextbox -Name 'SelectedProcesses' -Value ($selected -join "`n") + ) + } + } + + $stopModal = New-PodeWebModal -Name 'StopSelected' -DisplayName 'Stop Selected Processes' -Size 'Medium' -AsForm -Content @( + New-PodeWebTextbox -Name 'SelectedProcesses' -DisplayName 'Selected Process IDs' -Multiline -ReadOnly + ) -ScriptBlock { + $ids = ($WebEvent.Data['SelectedProcesses'] -split "`n") | Where-Object { ![string]::IsNullOrWhiteSpace($_) } + foreach ($id in $ids) { + Stop-Process -Id ([int]$id) -Force -ErrorAction SilentlyContinue -WhatIf + } + Show-PodeWebToast -Message "Stopped $($ids.Count) process(es)" -Title 'Done' -Duration 3000 + Hide-PodeWebModal + } + + $card3 = New-PodeWebCard -Name 'MultiSelect Processes' -Content $multiTable + + Add-PodeWebPage -Name 'Home' -Path '/' -HomePage -Content $card1, $card2, $card3, $stopModal -Title 'Tables' } \ No newline at end of file diff --git a/src/Public/Elements.ps1 b/src/Public/Elements.ps1 index cfb58763..258f2e81 100644 --- a/src/Public/Elements.ps1 +++ b/src/Public/Elements.ps1 @@ -2915,6 +2915,9 @@ function New-PodeWebTable { [switch] $AutoRefresh, + [switch] + $MultiSelect, + [switch] $AsCard ) @@ -2968,6 +2971,7 @@ function New-PodeWebTable { RefreshInterval = ($RefreshInterval * 1000) NoRefresh = $NoRefresh.IsPresent NoAuthentication = $NoAuthentication.IsPresent + MultiSelect = $MultiSelect.IsPresent Paging = @{ Enabled = $Paginate.IsPresent Size = $PageSize diff --git a/src/Templates/Public/scripts/templates.js b/src/Templates/Public/scripts/templates.js index 2e624091..073581c0 100644 --- a/src/Templates/Public/scripts/templates.js +++ b/src/Templates/Public/scripts/templates.js @@ -2881,6 +2881,7 @@ class PodeTable extends PodeRefreshableElement { this.dataColumn = data.DataColumn; this.clickableRows = data.Click ?? false; this.clickIsDynamic = data.ClickIsDynamic ?? false; + this.multiSelect = data.MultiSelect ?? false; this.exportable = { enabled: data.Export ?? false @@ -2943,7 +2944,8 @@ class PodeTable extends PodeRefreshableElement {