diff --git a/docs/Getting-Started/Migrating/08-to-10.md b/docs/Getting-Started/Migrating/08-to-10.md
index 23fb103a..87727224 100644
--- a/docs/Getting-Started/Migrating/08-to-10.md
+++ b/docs/Getting-Started/Migrating/08-to-10.md
@@ -153,6 +153,37 @@ Because of this change, functions that had `-Layouts` or `-Elements` parameters
Originally, within the scriptblock of a dynamic element, if you wanted to access the data of an element's parent you could do so via `$ElementData.Parent`. This has now been changed, and the data is accessible via a new `$ParentData` instead - this has been done to stop the `$ElementData` object from getting too large, and to reduce network data transfer to better support SSE.
+### Selects
+
+Select elements have been changed primarily in the way you supply Options. Originally you would create a Select via `New-PodeWebSelect` and supply `-Options` as a string array, and optionally `-DisplayOptions` or `-SelectedValue`.
+
+Now, you can create Options via the new `New-PodeWebOption` function - and even group them via `New-PodeWebOptionGroup`. The `-Options` on `New-PodeWebSelect` now accepts an array of these elements, and the `-DisplayOptions` and `-SelectedValue` have moved to `New-PodeWebOption` as `-DisplayName` and `-Selected` respectively.
+
+For example, the following previous Select element:
+
+```powershell
+New-PodeWebSelect -Name 'Example' -Options @('Option1', 'Option2') -SelectedValue 'Option1'
+```
+
+Would now be the following instead:
+
+```powershell
+New-PodeWebSelect -Name 'Example' -Options @(
+ New-PodeWebOption -Name 'Option1' -Selected
+ New-PodeWebOption -Name 'Option2'
+)
+```
+
+To assist with most migrations there is a helper function: `ConvertTo-PodeWebOption`. You can pipe an original raw string array into this, along with an optional `-SelectedOption` value, and it will convert to strings into Option elements for you:
+
+```powershell
+New-PodeWebSelect -Name 'Example' -Options @(
+ @('Option1', 'Option2') | ConvertTo-PodeWebOption -SelectedOption 'Option1'
+)
+```
+
+The `Update-PodeWebSelect` action sees the same update as well. Additionally the `-Value` on `Set-PodeWebSelect` is now `-OptionName`.
+
## Classes and Styles
All element functions have had the `-CssClass` and `-CssStyle` parameters removed. Instead, you can now pipe the element into either `Add-PodeWebClass` or `Add-PodeWebStyle`:
diff --git a/docs/Tutorials/Actions/Datalist.md b/docs/Tutorials/Actions/Datalist.md
new file mode 100644
index 00000000..73794457
--- /dev/null
+++ b/docs/Tutorials/Actions/Datalist.md
@@ -0,0 +1,126 @@
+# Datalist
+
+This page details the actions available to Datalist elements.
+
+## Add
+
+To add one or more Options you can use [`Add-PodeWebDatalistOption`](../../../Functions/Actions/Add-PodeWebDatalistOption) along with `-Option`:
+
+```powershell
+New-PodeWebContainer -NoBackground -Content @(
+ New-PodeWebDatalist -Name 'Example' -Options @(
+ New-PodeWebOption -Name 'Option1'
+ New-PodeWebOption -Name 'Option2'
+ )
+
+ New-PodeWebButton -Name 'Add Option' -ScriptBlock {
+ Add-PodeWebDatalistOption -Name 'Example' -Option @(
+ New-PodeWebOption -Name 'Added1'
+ )
+ }
+)
+```
+
+## Clear
+
+To clear the options of a Datalist element, you can use [`Clear-PodeWebDatalist`](../../../Functions/Actions/Clear-PodeWebDatalist):
+
+```powershell
+New-PodeWebContainer -NoBackground -Content @(
+ New-PodeWebDatalist -Name 'Example' -Options @(
+ New-PodeWebOption -Name 'Option1'
+ New-PodeWebOption -Name 'Option2'
+ New-PodeWebOption -Name 'Option3'
+ )
+
+ New-PodeWebButton -Name 'Clear Datalist' -ScriptBlock {
+ Clear-PodeWebDatalist -Name 'Example'
+ }
+)
+```
+
+## Remove
+
+To remove one or more Options you can use [`Remove-PodeWebDatalistOption`](../../../Functions/Actions/Remove-PodeWebDatalistOption) along with `-OptionName`:
+
+```powershell
+New-PodeWebContainer -NoBackground -Content @(
+ New-PodeWebDatalist -Name 'Example' -Options @(
+ New-PodeWebOption -Name 'Option1'
+ New-PodeWebOption -Name 'Option2'
+ New-PodeWebOption -Name 'Option3'
+ )
+
+ New-PodeWebButton -Name 'Remove Options' -ScriptBlock {
+ Remove-PodeWebDatalistOption -Name 'Example' -OptionName 'Option1', 'Option3'
+ }
+)
+```
+
+## Set
+
+To set the currently selected option/value of a Datalist element, you can use [`Set-PodeWebDatalist`](../../../Functions/Actions/Set-PodeWebDatalist). You can either set the value to a predefined option, or to a custom value not in the options list:
+
+```powershell
+New-PodeWebContainer -NoBackground -Content @(
+ New-PodeWebDatalist -Name 'Example' -Options @(
+ New-PodeWebOption -Name 'Option1'
+ New-PodeWebOption -Name 'Option2'
+ New-PodeWebOption -Name 'Option3'
+ )
+
+ New-PodeWebButton -Name 'Update Datalist Predefined' -ScriptBlock {
+ $rand = Get-Random -Minimum 0 -Maximum 3
+ $opt = (@('Option1', 'Option2', 'Option3'))[$rand]
+ Set-PodeWebDatalist -Name 'Example' -Value $opt
+ }
+
+ New-PodeWebButton -Name 'Update Datalist Custom' -ScriptBlock {
+ Set-PodeWebDatalist -Name 'Example' -Value 'Custom Value'
+ }
+)
+```
+
+## Sync
+
+If you built a Datalist element with the `-ScriptBlock` parameter, then you can re-invoke the scriptblock to update the element by using [`Sync-PodeWebDatalist`](../../../Functions/Actions/Sync-PodeWebDatalist):
+
+```powershell
+New-PodeWebContainer -NoBackground -Content @(
+ New-PodeWebDatalist -Name 'Example' -ScriptBlock {
+ foreach ($i in (1..10)) {
+ Get-Random -Minimum 1 -Maximum 10
+ }
+ }
+
+ New-PodeWebButton -Name 'Sync Datalist' -ScriptBlock {
+ Sync-PodeWebDatalist -Name 'Example'
+ }
+)
+```
+
+## Update
+
+You can update a Datalist element's options by using [`Update-PodeWebDatalist`](../../../Functions/Actions/Update-PodeWebDatalist):
+
+```powershell
+New-PodeWebContainer -NoBackground -Content @(
+ New-PodeWebDatalist -Name 'Example' -ScriptBlock {
+ foreach ($i in (1..10)) {
+ Get-Random -Minimum 1 -Maximum 10
+ }
+ }
+
+ New-PodeWebButton -Name 'New Options' -ScriptBlock {
+ $options = @(foreach ($i in (1..10)) {
+ Get-Random -Minimum 1 -Maximum 10
+ })
+
+ $options |
+ ConvertTo-PodeWebOption |
+ Update-PodeWebDatalist -Name 'Example'
+ }
+)
+```
+
+Various other properties can be updated as well.
diff --git a/docs/Tutorials/Actions/Error.md b/docs/Tutorials/Actions/Error.md
index 4f145a74..246b5e2f 100644
--- a/docs/Tutorials/Actions/Error.md
+++ b/docs/Tutorials/Actions/Error.md
@@ -14,7 +14,9 @@ New-PodeWebCard -Content @(
New-PodeWebTextbox -Name 'Name'
New-PodeWebTextbox -Name 'Password' -Type Password -PrependIcon Lock
New-PodeWebCheckbox -Name 'Checkboxes' -Options @('Terms', 'Privacy') -AsSwitch
- New-PodeWebSelect -Name 'Role' -Options @('User', 'Admin', 'Operations') -Multiple
+ New-PodeWebSelect -Name 'Role' -Multiple -Options @(
+ @('User', 'Admin', 'Operations') | ConvertTo-PodeWebOption
+ )
)
)
```
diff --git a/docs/Tutorials/Actions/Form.md b/docs/Tutorials/Actions/Form.md
index 8ce16219..b03c5902 100644
--- a/docs/Tutorials/Actions/Form.md
+++ b/docs/Tutorials/Actions/Form.md
@@ -12,7 +12,9 @@ New-PodeWebCard -Content @(
New-PodeWebTextbox -Name 'Name'
New-PodeWebTextbox -Name 'Password' -Type Password -PrependIcon Lock
New-PodeWebCheckbox -Name 'Checkboxes' -Options @('Terms', 'Privacy') -AsSwitch
- New-PodeWebSelect -Name 'Role' -Options @('User', 'Admin', 'Operations') -Multiple
+ New-PodeWebSelect -Name 'Role' -Multiple -Options @(
+ @('User', 'Admin', 'Operations') | ConvertTo-PodeWebOption
+ )
)
)
@@ -33,7 +35,9 @@ New-PodeWebCard -Content @(
New-PodeWebTextbox -Name 'Name'
New-PodeWebTextbox -Name 'Password' -Type Password -PrependIcon Lock
New-PodeWebCheckbox -Name 'Checkboxes' -Options @('Terms', 'Privacy') -AsSwitch
- New-PodeWebSelect -Name 'Role' -Options @('User', 'Admin', 'Operations') -Multiple
+ New-PodeWebSelect -Name 'Role' -Multiple -Options @(
+ @('User', 'Admin', 'Operations') | ConvertTo-PodeWebOption
+ )
)
)
diff --git a/docs/Tutorials/Actions/Select.md b/docs/Tutorials/Actions/Select.md
index 770b15b4..c7cdb04a 100644
--- a/docs/Tutorials/Actions/Select.md
+++ b/docs/Tutorials/Actions/Select.md
@@ -2,32 +2,101 @@
This page details the actions available to Select elements.
+## Add
+
+To add one or more Options, or Option Groups, you can use [`Add-PodeWebSelectOption`](../../../Functions/Actions/Add-PodeWebSelectOption) along with `-Option` and optionally a `-GroupName` to place the options under:
+
+```powershell
+New-PodeWebContainer -NoBackground -Content @(
+ New-PodeWebSelect -Name 'Example' -Options @(
+ New-PodeWebOptionGroup -Name 'Group1' -Options @(
+ New-PodeWebOption -Name 'Option1'
+ )
+ New-PodeWebOption -Name 'Option2'
+ )
+
+ New-PodeWebButton -Name 'Add Option' -ScriptBlock {
+ Add-PodeWebSelectOption -Name 'Example' -Option @(
+ New-PodeWebOption -Name 'Added1'
+ )
+ }
+
+ New-PodeWebButton -Name 'Add Option to Group' -ScriptBlock {
+ Add-PodeWebSelectOption -Name 'Example' -GroupName 'Group1' -Option @(
+ New-PodeWebOption -Name 'Added1'
+ )
+ }
+
+ New-PodeWebButton -Name 'Add Options and Group' -ScriptBlock {
+ Add-PodeWebSelectOption -Name 'Example' -Option @(
+ New-PodeWebOptionGroup -Name 'AddedGroup1' -Options @(
+ New-PodeWebOption -Name 'Added1'
+ )
+ )
+ }
+)
+```
+
## Clear
To clear the options of a Select element, you can use [`Clear-PodeWebSelect`](../../../Functions/Actions/Clear-PodeWebSelect):
```powershell
New-PodeWebContainer -NoBackground -Content @(
- New-PodeWebSelect -Name Options -Options Option1, Option2, Option3
+ New-PodeWebSelect -Name 'Example' -Options @(
+ New-PodeWebOption -Name 'Option1'
+ New-PodeWebOption -Name 'Option2'
+ New-PodeWebOption -Name 'Option3'
+ )
New-PodeWebButton -Name 'Clear Select' -ScriptBlock {
- Clear-PodeWebSelect -Name Options
+ Clear-PodeWebSelect -Name 'Example'
+ }
+)
+```
+
+## Remove
+
+To remove one or more Options, or Option Groups, you can use [`Remove-PodeWebSelectOption`](../../../Functions/Actions/Remove-PodeWebSelectOption) along with `-OptionName` and/or `-GroupName`:
+
+```powershell
+New-PodeWebContainer -NoBackground -Content @(
+ New-PodeWebSelect -Name 'Example' -Options @(
+ New-PodeWebOptionGroup -Name 'Group1' -Options @(
+ New-PodeWebOption -Name 'Option1'
+ )
+ New-PodeWebOptionGroup -Name 'Group2' -Options @(
+ New-PodeWebOption -Name 'Option2'
+ New-PodeWebOption -Name 'Option3'
+ )
+ )
+
+ New-PodeWebButton -Name 'Remove Groups' -ScriptBlock {
+ Remove-PodeWebSelectOption -Name 'Example' -GroupName 'Group1', 'Group2'
+ }
+
+ New-PodeWebButton -Name 'Remove Options' -ScriptBlock {
+ Remove-PodeWebSelectOption -Name 'Example' -OptionName 'Option1', 'Option3'
}
)
```
## Set
-To set the currently selected option/value of a select element, you can use [`Set-PodeWebSelect`](../../../Functions/Actions/Set-PodeWebSelect):
+To set the currently selected option/value of a Select element, you can use [`Set-PodeWebSelect`](../../../Functions/Actions/Set-PodeWebSelect):
```powershell
New-PodeWebContainer -NoBackground -Content @(
- New-PodeWebSelect -Name Options -Options Option1, Option2, Option3
+ New-PodeWebSelect -Name 'Example' -Options @(
+ New-PodeWebOption -Name 'Option1'
+ New-PodeWebOption -Name 'Option2'
+ New-PodeWebOption -Name 'Option3'
+ )
New-PodeWebButton -Name 'Update Select' -ScriptBlock {
$rand = Get-Random -Minimum 0 -Maximum 3
$opt = (@('Option1', 'Option2', 'Option3'))[$rand]
- Set-PodeWebSelect -Name Options -Value $opt
+ Set-PodeWebSelect -Name 'Example' -OptionName $opt
}
)
```
@@ -38,14 +107,14 @@ If you built a Select element with the `-ScriptBlock` parameter, then you can re
```powershell
New-PodeWebContainer -NoBackground -Content @(
- New-PodeWebSelect -Name Options --ScriptBlock {
- return @(foreach ($i in (1..10)) {
+ New-PodeWebSelect -Name 'Example' -ScriptBlock {
+ foreach ($i in (1..10)) {
Get-Random -Minimum 1 -Maximum 10
- })
+ }
}
New-PodeWebButton -Name 'Sync Select' -ScriptBlock {
- Sync-PodeWebSelect -Name Options
+ Sync-PodeWebSelect -Name 'Example'
}
)
```
@@ -56,10 +125,10 @@ You can update a Select element's options by using [`Update-PodeWebSelect`](../.
```powershell
New-PodeWebContainer -NoBackground -Content @(
- New-PodeWebSelect -Name Options --ScriptBlock {
- return @(foreach ($i in (1..10)) {
+ New-PodeWebSelect -Name 'Example' -ScriptBlock {
+ foreach ($i in (1..10)) {
Get-Random -Minimum 1 -Maximum 10
- })
+ }
}
New-PodeWebButton -Name 'New Options' -ScriptBlock {
@@ -67,11 +136,11 @@ New-PodeWebContainer -NoBackground -Content @(
Get-Random -Minimum 1 -Maximum 10
})
- $options | Update-PodeWebSelect -Name Options
+ $options |
+ ConvertTo-PodeWebOption |
+ Update-PodeWebSelect -Name 'Example'
}
)
```
-You can also optionally supply `-DisplayOptions` to alter the values displayed in the Select element, as well as also supply as `-SelectedValue`.
-
Various other properties can be updated as well.
diff --git a/docs/Tutorials/Actions/Validation.md b/docs/Tutorials/Actions/Validation.md
index 79582056..6b480481 100644
--- a/docs/Tutorials/Actions/Validation.md
+++ b/docs/Tutorials/Actions/Validation.md
@@ -27,7 +27,9 @@ New-PodeWebCard -Content @(
} -Content @(
New-PodeWebTextbox -Name 'Username'
New-PodeWebTextbox -Name 'Password' -Type Password -PrependIcon Lock
- New-PodeWebSelect -Name 'Role' -Options @('User', 'Admin') -Multiple
+ New-PodeWebSelect -Name 'Role' -Multiple -Options @(
+ @('User', 'Admin') | ConvertTo-PodeWebOption
+ )
)
)
```
diff --git a/docs/Tutorials/ElementData.md b/docs/Tutorials/ElementData.md
index 5abd62c8..6ab43483 100644
--- a/docs/Tutorials/ElementData.md
+++ b/docs/Tutorials/ElementData.md
@@ -12,7 +12,7 @@ New-PodeWebSelect -Name 'Random' -ScriptBlock {
Get-Random -Minimum 1 -Maximum 10
})
- $options | Update-PodeWebSelect -Id $ElementData.Id
+ $options | ConvertTo-PodeWebOption | Update-PodeWebSelect -Id $ElementData.Id
}
```
diff --git a/docs/Tutorials/Elements/Datalist.md b/docs/Tutorials/Elements/Datalist.md
new file mode 100644
index 00000000..345021ef
--- /dev/null
+++ b/docs/Tutorials/Elements/Datalist.md
@@ -0,0 +1,71 @@
+# Datalist
+
+| Support | |
+| ------- | --- |
+| Events | Yes |
+
+The Datalist element is a form input element, and can be added using [`New-PodeWebDatalist`](../../../Functions/Elements/New-PodeWebDatalist). This will add a textbox input element but with an "autocomplete" select-like dropdown menu, allowing the user to select either a predefined option or supply a custom value.
+
+## Options
+
+To create a Datalist element with pre-defined options, you can use the `-Options` parameter which accepts an array of [`New-PodeWebOption`](../../../Functions/Elements/New-PodeWebOption):
+
+```powershell
+New-PodeWebCard -Content @(
+ New-PodeWebForm -Name 'Example' -ScriptBlock {
+ $value = $WebEvent.Data['DatalistExample']
+ } -Content @(
+ New-PodeWebDatalist -Name 'DatalistExample' -Options @(
+ New-PodeWebOption -Name 'Text'
+ New-PodeWebOption -Name 'Xml'
+ New-PodeWebOption -Name 'Json' -Selected
+ New-PodeWebOption -Name 'Csv'
+ )
+ )
+)
+```
+
+### Dynamic
+
+You can build a Datalist element's options dynamically by using the `-ScriptBlock` parameter. This will allow you to retrieve the options from elsewhere for use with the Datalist element.
+
+You can either return an array of raw values, or pipe the options into, and return, [`Update-PodeWebDatalist`](../../../Functions/Actions/Update-PodeWebDatalist). When using the latter you will need to supply the options as Option elements, for this you can either build the options using [`New-PodeWebOption`](../../../Functions/Elements/New-PodeWebOption) or convert raw values via [`ConvertTo-PodeWebOption`](../../../Functions/Elements/ConvertTo-PodeWebOption).
+
+The following will both build a Datalist element with 10 random numbers as the options, using the above methods:
+
+```powershell
+New-PodeWebCard -Content @(
+ New-PodeWebForm -Name 'Example' -ScriptBlock {
+ # return raw values for Pode.Web to convert
+ New-PodeWebDatalist -Name 'RawValues' -ScriptBlock {
+ foreach ($i in (1..10)) {
+ Get-Random -Minimum 1 -Maximum 10
+ }
+ }
+
+ # use New-PodeWebOption
+ New-PodeWebDatalist -Name 'NewToUpdate' -ScriptBlock {
+ $options = @(foreach ($i in (1..10)) {
+ New-PodeWebOption -Name (Get-Random -Minimum 1 -Maximum 10)
+ })
+
+ $options | Update-PodeWebDatalist -Id $ElementData.Id
+ }
+
+ # use ConvertTo-PodeWebOption
+ New-PodeWebDatalist -Name 'NewToUpdate' -ScriptBlock {
+ $options = @(foreach ($i in (1..10)) {
+ Get-Random -Minimum 1 -Maximum 10
+ })
+
+ $options |
+ ConvertTo-PodeWebOption |
+ Update-PodeWebDatalist -Id $ElementData.Id
+ }
+ }
+)
+```
+
+## Display Name
+
+By default the label displays the `-Name` of the element. You can change the value displayed by also supplying an optional `-DisplayName` value; this value is purely visual, when the user submits the form the value of the element is still retrieved using the `-Name` from `$WebEvent.Data`.
diff --git a/docs/Tutorials/Elements/Form.md b/docs/Tutorials/Elements/Form.md
index 6dfdee7a..0cd0da0a 100644
--- a/docs/Tutorials/Elements/Form.md
+++ b/docs/Tutorials/Elements/Form.md
@@ -21,7 +21,9 @@ New-PodeWebCard -Content @(
New-PodeWebCredential -Name 'Credentials'
New-PodeWebCheckbox -Name 'Checkboxes' -Options @('Terms', 'Privacy') -AsSwitch
New-PodeWebRadio -Name 'Radios' -Options @('S', 'M', 'L')
- New-PodeWebSelect -Name 'Role' -Options @('User', 'Admin', 'Operations') -Multiple
+ New-PodeWebSelect -Name 'Role' -Multiple -Options @(
+ @('User', 'Admin', 'Operations') | ConvertTo-PodeWebOption
+ )
New-PodeWebRange -Name 'Cores' -Value 30 -ShowValue
)
)
diff --git a/docs/Tutorials/Elements/Modal.md b/docs/Tutorials/Elements/Modal.md
index 605f55f6..742cd5ad 100644
--- a/docs/Tutorials/Elements/Modal.md
+++ b/docs/Tutorials/Elements/Modal.md
@@ -86,7 +86,9 @@ New-PodeWebCard -Content @(
)
New-PodeWebModal -Name 'Edit Service' -AsForm -Content @(
- New-PodeWebSelect -Name 'StartType' -Options Manual, Automatic, Disabled
+ New-PodeWebSelect -Name 'StartType' -Options @(
+ 'Manual', 'Automatic', 'Disabled' | ConvertTo-PodeWebOption
+ )
) -ScriptBlock {
Get-Service -Name $WebEvent.Data.Value | Set-Service -StartType $WebEvent.Data.StartType | Out-Null
Show-PodeWebToast -Message "$($WebEvent.Data.Value) edited"
diff --git a/docs/Tutorials/Elements/Select.md b/docs/Tutorials/Elements/Select.md
index adf514c5..efa4829f 100644
--- a/docs/Tutorials/Elements/Select.md
+++ b/docs/Tutorials/Elements/Select.md
@@ -1,29 +1,42 @@
# Select
-| Support | |
-| ------- |-|
-| Events | Yes |
+| Support | |
+| ------- | --- |
+| Events | Yes |
-The Select element is a form input element, and can be added using [`New-PodeWebSelect`](../../../Functions/Elements/New-PodeWebSelect). This will add a dropdown select menu to your form, allowing the user to select an entry; to allow multiple entries to be selected you can pass `-Multiple`, and to specify a pre-selected value you can use `-SelectedValue`.
+The Select element is a form input element, and can be added using [`New-PodeWebSelect`](../../../Functions/Elements/New-PodeWebSelect). This will add a dropdown select menu to your form/page, allowing the user to select an entry - or multiple entries by passing `-Multiple`.
## Options
-To create a Select element with pre-defined options, you can use the `-Options` parameter:
+To create a Select element with pre-defined options, you can use the `-Options` parameter which accepts an array of either [`New-PodeWebOption`](../../../Functions/Elements/New-PodeWebOption) and/or [`New-PodeWebOptionGroup`](../../../Functions/Elements/New-PodeWebOptionGroup):
```powershell
New-PodeWebCard -Content @(
New-PodeWebForm -Name 'Example' -ScriptBlock {
- $single = $WebEvent.Data['Single']
- $multiple = $WebEvent.Data['Multiple']
+ $single = $WebEvent.Data['SingleExample']
+ $multiple = $WebEvent.Data['MultipleExample']
} -Content @(
- New-PodeWebSelect -Name 'Single' -Options 'Text', 'Xml', 'Json', 'Csv' -SelectedValue 'Json'
- New-PodeWebSelect -Name 'Multiple' -Options 'Text', 'Xml', 'Json', 'Csv' -Multiple
+ New-PodeWebSelect -Name 'SingleExample' -Options @(
+ New-PodeWebOption -Name 'Text'
+ New-PodeWebOption -Name 'Xml'
+ New-PodeWebOption -Name 'Json' -Selected
+ New-PodeWebOption -Name 'Csv'
+ )
+
+ New-PodeWebSelect -Name 'MultipleExample' -Multiple -Options @(
+ New-PodeWebOptionGroup -Name 'Types' -Options (
+ New-PodeWebOption -Name 'Text'
+ New-PodeWebOption -Name 'Xml'
+ New-PodeWebOption -Name 'Json'
+ New-PodeWebOption -Name 'Csv'
+ )
+ )
)
)
```
!!! Note
- When using `-Multiple`, the values will be sent back in a comma separated list
+ When using `-Multiple`, the selected values will be sent back to the server as a comma-separated list
Which looks like below:
@@ -31,25 +44,40 @@ Which looks like below:
### Dynamic
-You can build a Select element's options dynamically by using the `-ScriptBlock` parameter. This will allow you to retrieve the options from elsewhere and use them as options instead.
+You can build a Select element's options dynamically by using the `-ScriptBlock` parameter. This will allow you to retrieve the options from elsewhere for use with the Select element.
-You can either return an array of raw values, or pipe the options into, and return, [`Update-PodeWebSelect`](../../../Functions/Actions/Update-PodeWebSelect). The following will both build a Select element with 10 random numbers as the options:
+You can either return an array of raw values, or pipe the options into, and return, [`Update-PodeWebSelect`](../../../Functions/Actions/Update-PodeWebSelect). When using the latter you will need to supply the options as Option elements, for this you can either build the options using [`New-PodeWebOption`](../../../Functions/Elements/New-PodeWebOption) or convert raw values via [`ConvertTo-PodeWebOption`](../../../Functions/Elements/ConvertTo-PodeWebOption).
+
+The following will both build a Select element with 10 random numbers as the options, using the above methods:
```powershell
New-PodeWebCard -Content @(
New-PodeWebForm -Name 'Example' -ScriptBlock {
- New-PodeWebSelect -Name 'Random1' -ScriptBlock {
- return @(foreach ($i in (1..10)) {
+ # return raw values for Pode.Web to convert
+ New-PodeWebSelect -Name 'RawValues' -ScriptBlock {
+ foreach ($i in (1..10)) {
Get-Random -Minimum 1 -Maximum 10
+ }
+ }
+
+ # use New-PodeWebOption
+ New-PodeWebSelect -Name 'NewToUpdate' -ScriptBlock {
+ $options = @(foreach ($i in (1..10)) {
+ New-PodeWebOption -Name (Get-Random -Minimum 1 -Maximum 10)
})
+
+ $options | Update-PodeWebSelect -Id $ElementData.Id
}
- New-PodeWebSelect -Name 'Random2' -ScriptBlock {
+ # use ConvertTo-PodeWebOption
+ New-PodeWebSelect -Name 'NewToUpdate' -ScriptBlock {
$options = @(foreach ($i in (1..10)) {
Get-Random -Minimum 1 -Maximum 10
})
- $options | Update-PodeWebSelect -Id $ElementData.Id
+ $options |
+ ConvertTo-PodeWebOption |
+ Update-PodeWebSelect -Id $ElementData.Id
}
}
)
@@ -62,7 +90,3 @@ You can render a multiple select element, where more than one option can be sele
## Display Name
By default the label displays the `-Name` of the element. You can change the value displayed by also supplying an optional `-DisplayName` value; this value is purely visual, when the user submits the form the value of the element is still retrieved using the `-Name` from `$WebEvent.Data`.
-
-## Display Options
-
-By default the options displayed are from the `-Options` parameter. Like the Name, you can change the values displayed by supplying the optional `-DisplayOptions` - values in the array should be in the same order as the values in `-Options`. These values are, like the Display Name, purely visual, and when the form is submitted the server receives the original values from `-Options`.
diff --git a/docs/Tutorials/Events.md b/docs/Tutorials/Events.md
index 3cc2a3d2..3677bba4 100644
--- a/docs/Tutorials/Events.md
+++ b/docs/Tutorials/Events.md
@@ -29,7 +29,9 @@ Let's say you want to have a Select element, but not in a form. When the Select'
### Server-Side
```powershell
-New-PodeWebSelect -Name 'Role' -Options @('Choose...', 'User', 'Admin', 'Operations') |
+New-PodeWebSelect -Name 'Role' -Options @(
+ @('Choose...', 'User', 'Admin', 'Operations') | ConvertTo-PodeWebOption
+ ) |
Register-PodeWebEvent -Type Change -ScriptBlock {
Show-PodeWebToast -Message "The value was changed: $($WebEvent.Data['Role'])"
}
@@ -40,7 +42,9 @@ If the element the event triggers for is a form input element, the value will be
### Client-Side
```powershell
-New-PodeWebSelect -Name 'Role' -Options @('Choose...', 'User', 'Admin', 'Operations') |
+New-PodeWebSelect -Name 'Role' -Options @(
+ @('Choose...', 'User', 'Admin', 'Operations') | ConvertTo-PodeWebOption
+ ) |
Register-PodeWebEvent -Type Change -JSFunction 'invokeCustomEvent'
```
diff --git a/examples/input_events.ps1 b/examples/input_events.ps1
index ff264589..1e1d4026 100644
--- a/examples/input_events.ps1
+++ b/examples/input_events.ps1
@@ -13,7 +13,9 @@ Start-PodeServer -Threads 2 {
# select event
$select = New-PodeWebContainer -Content @(
New-PodeWebText -Value 'Please select a value: '
- New-PodeWebSelect -Name 'Bellows' -Options 'Bellow 1', 'Bellow 2', 'Bellow 3' |
+ New-PodeWebSelect -Name 'Bellows' -Options @(
+ @('Bellow 1', 'Bellow 2', 'Bellow 3') | ConvertTo-PodeWebOption
+ ) |
Register-PodeWebEvent -Type Change -ScriptBlock {
Open-PodeWebBellow -Name $WebEvent.Data['Bellows']
}
@@ -43,7 +45,7 @@ Start-PodeServer -Threads 2 {
Sort-Object -Property CPU -Descending |
Select-Object -First 15 -Property Name, ID, WorkingSet, CPU |
Update-PodeWebTable -Name 'Processes'
- }
+ }
New-PodeWebLine
New-PodeWebTable -Name 'Processes'
)
diff --git a/examples/inputs.ps1 b/examples/inputs.ps1
index 9ce6488c..b0d63e03 100644
--- a/examples/inputs.ps1
+++ b/examples/inputs.ps1
@@ -38,16 +38,43 @@ Start-PodeServer -Threads 2 {
New-PodeWebCredential -Name 'Credentials'
New-PodeWebMinMax -Name 'CPU' -AppendIcon 'percent' -ReadOnly
New-PodeWebCheckbox -Name 'Switches' -Options @('Terms', 'Privacy') -AsSwitch
- New-PodeWebCheckbox -Name 'Checkboxes' -Options @('Terms', 'Privacy') -Inline
- New-PodeWebRadio -Name 'Radios' -Options @('S', 'M', 'L')
- New-PodeWebSelect -Name 'Role1' -Options @('Choose...', 'User', 'Admin', 'Operations') -PrependIcon 'account' -AppendIcon 'account'
- New-PodeWebSelect -Name 'Role2' -Options @('User', 'Admin', 'Operations') -Multiple
- New-PodeWebRange -Name 'Cores' -Value 30 -ShowValue
+ New-PodeWebCheckbox -Name 'Checkboxes' -Options @('Terms', 'Privacy') -Inline -HelpText 'Accept the terms and privacy policy'
+ New-PodeWebRadio -Name 'Radios' -Options @('S', 'M', 'L') -HelpText 'Select a size'
+
+ New-PodeWebSelect -Name 'Role1' -PrependIcon 'account' -AppendIcon 'account' -HelpText 'Select a role' -Options @(
+ @('Choose...', 'User', 'Admin', 'Operations') | ConvertTo-PodeWebOption
+ )
+
+ New-PodeWebSelect -Name 'Role2' -Multiple -Options @(
+ New-PodeWebOptionGroup -Name 'General' -Options @(
+ New-PodeWebOption -Name 'User'
+ )
+ New-PodeWebOptionGroup -Name 'Administrative' -Options @(
+ New-PodeWebOption -Name 'Admin'
+ New-PodeWebOption -Name 'Operations' -Selected
+ )
+ )
+
+ New-PodeWebDatalist -Name 'Browsers' -Placeholder 'Select a browser' -Options @(
+ New-PodeWebOption -Name 'Chrome'
+ New-PodeWebOption -Name 'Firefox'
+ New-PodeWebOption -Name 'Edge'
+ New-PodeWebOption -Name 'Safari' -Selected
+ New-PodeWebOption -Name 'Opera'
+ )
+
+ New-PodeWebDatalist -Name 'Count' -Placeholder 'Select a value' -ScriptBlock {
+ foreach ($i in (1..10)) {
+ Get-Random -Minimum 1 -Maximum 10
+ }
+ }
+
+ New-PodeWebRange -Name 'Cores' -Value 30 -ShowValue -HelpText 'Select a number of CPU cores'
New-PodeWebSelect -Name 'Amount' -ScriptBlock {
- return @(foreach ($i in (1..10)) {
- Get-Random -Minimum 1 -Maximum 10
- })
+ foreach ($i in (1..10)) {
+ Get-Random -Minimum 1 -Maximum 10
+ }
} |
Register-PodeWebEvent -Type Change -ScriptBlock {
Show-PodeWebToast -Message "The value was changed: $($WebEvent.Data['Amount'])"
@@ -87,7 +114,7 @@ Start-PodeServer -Threads 2 {
Get-Random -Minimum 1 -Maximum 10
})
- $options | Update-PodeWebSelect -Name 'DynamicSelect'
+ $options | ConvertTo-PodeWebOption | Update-PodeWebSelect -Name 'DynamicSelect'
}
New-PodeWebButton -Name 'Clear Options' -ScriptBlock {
@@ -99,11 +126,35 @@ Start-PodeServer -Threads 2 {
}
New-PodeWebSelect -Name 'DynamicSelect' -Multiple -Size 6 -ScriptBlock {
- return @(foreach ($i in (1..10)) {
+ foreach ($i in (1..10)) {
+ Get-Random -Minimum 1 -Maximum 10
+ }
+ }
+ )
+
+ $container3 = New-PodeWebContainer -Content @(
+ New-PodeWebButton -Name 'New List' -ScriptBlock {
+ $options = @(foreach ($i in (1..10)) {
Get-Random -Minimum 1 -Maximum 10
})
+
+ $options | ConvertTo-PodeWebOption | Update-PodeWebDatalist -Name 'DynamicDatalist'
+ }
+
+ New-PodeWebButton -Name 'Clear List' -ScriptBlock {
+ Clear-PodeWebDatalist -Name 'DynamicDatalist'
+ }
+
+ New-PodeWebButton -Name 'Resync List' -ScriptBlock {
+ Sync-PodeWebDatalist -Name 'DynamicDatalist'
+ }
+
+ New-PodeWebDatalist -Name 'DynamicDatalist' -ScriptBlock {
+ foreach ($i in (1..10)) {
+ Get-Random -Minimum 1 -Maximum 10
+ }
}
)
- Add-PodeWebPage -Name 'Home' -Path '/' -Content $form, $container1, $modal, $container2 -Title 'Testing Inputs' -HomePage
+ Add-PodeWebPage -Name 'Home' -Path '/' -Content $form, $container1, $modal, $container2, $container3 -Title 'Testing Inputs' -HomePage
}
\ No newline at end of file
diff --git a/src/Public/Actions.ps1 b/src/Public/Actions.ps1
index 5c8f0c9d..8d38748a 100644
--- a/src/Public/Actions.ps1
+++ b/src/Public/Actions.ps1
@@ -793,7 +793,7 @@ function Set-PodeWebSelect {
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]
- $Value
+ $OptionName
)
Send-PodeWebAction -Value @{
@@ -801,11 +801,11 @@ function Set-PodeWebSelect {
ObjectType = 'Select'
Name = $Name
ID = $Id
- Value = [System.Net.WebUtility]::HtmlEncode($Value)
+ OptionName = [System.Net.WebUtility]::HtmlEncode($OptionName)
}
}
-function Update-PodeWebSelect {
+function Add-PodeWebSelectOption {
[CmdletBinding(DefaultParameterSetName = 'Name')]
param(
[Parameter(Mandatory = $true, ParameterSetName = 'Name')]
@@ -817,19 +817,101 @@ function Update-PodeWebSelect {
$Id,
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
- [string[]]
- $Options,
+ [hashtable[]]
+ $Option,
[Parameter()]
+ [string]
+ $GroupName
+ )
+
+ begin {
+ $items = @()
+ }
+
+ process {
+ $items += $Option
+ }
+
+ end {
+ # ensure options are only of type option or option-group
+ if ([string]::IsNullOrEmpty($GroupName)) {
+ if (!(Test-PodeWebContent -Content $items -ComponentType Element -ObjectType 'Option', 'Option-Group')) {
+ throw 'A Select can only contain Options or Option Groups'
+ }
+ }
+ else {
+ if (!(Test-PodeWebContent -Content $items -ComponentType Element -ObjectType 'Option')) {
+ throw 'A Select Option Group can only contain Options'
+ }
+ }
+
+ Send-PodeWebAction -Value @{
+ Operation = 'Add'
+ ObjectType = 'Select'
+ Name = $Name
+ ID = $Id
+ Options = $items
+ GroupName = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'GroupName' -Value $GroupName)
+ }
+ }
+}
+
+function Remove-PodeWebSelectOption {
+ [CmdletBinding(DefaultParameterSetName = 'Name')]
+ param(
+ [Parameter(Mandatory = $true, ParameterSetName = 'Name')]
+ [string]
+ $Name,
+
+ [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
+ [string]
+ $Id,
+
+ [Parameter(ValueFromPipeline = $true)]
[string[]]
- $DisplayOptions,
+ $OptionName,
[Parameter()]
[string[]]
- $SelectedValue,
+ $GroupName
+ )
+
+ Send-PodeWebAction -Value @{
+ Operation = 'Remove'
+ ObjectType = 'Select'
+ Name = $Name
+ ID = $Id
+ OptionName = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'OptionName' -Value $OptionName)
+ GroupName = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'GroupName' -Value $GroupName)
+ }
+}
+
+function Update-PodeWebSelect {
+ [CmdletBinding(DefaultParameterSetName = 'Name')]
+ param(
+ [Parameter(Mandatory = $true, ParameterSetName = 'Name')]
+ [string]
+ $Name,
+
+ [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
+ [string]
+ $Id,
+
+ [Parameter(ValueFromPipeline = $true)]
+ [hashtable[]]
+ $Options,
+
+ [Parameter()]
+ [ValidateSet(1, [int]::MaxValue)]
+ [int]
+ $Size,
[switch]
- $Disabled
+ $Disabled,
+
+ [switch]
+ $Multiple
)
begin {
@@ -841,15 +923,19 @@ function Update-PodeWebSelect {
}
end {
+ if (!(Test-PodeWebContent -Content $items -ComponentType Element -ObjectType 'Option', 'Option-Group')) {
+ throw 'A Select can only contain Options or Option Groups'
+ }
+
Send-PodeWebAction -Value @{
- Operation = 'Update'
- ObjectType = 'Select'
- Name = $Name
- ID = $Id
- Options = $items
- DisplayOptions = @(Protect-PodeWebValues -Value $DisplayOptions -Default $items -EqualCount)
- SelectedValue = @(Protect-PodeWebValues -Value $SelectedValue -Encode)
- Disabled = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'Disabled' -Value $Disabled.IsPresent)
+ Operation = 'Update'
+ ObjectType = 'Select'
+ Name = $Name
+ ID = $Id
+ Options = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'Options' -Value $items)
+ Size = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'Size' -Value $Size)
+ Multiple = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'Multiple' -Value $Multiple.IsPresent)
+ Disabled = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'Disabled' -Value $Disabled.IsPresent)
}
}
}
@@ -894,6 +980,195 @@ function Sync-PodeWebSelect {
}
}
+function Set-PodeWebDatalist {
+ [CmdletBinding(DefaultParameterSetName = 'Name')]
+ param(
+ [Parameter(Mandatory = $true, ParameterSetName = 'Name')]
+ [string]
+ $Name,
+
+ [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
+ [string]
+ $Id,
+
+ [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
+ [string]
+ $Value
+ )
+
+ Send-PodeWebAction -Value @{
+ Operation = 'Set'
+ ObjectType = 'Datalist'
+ Name = $Name
+ ID = $Id
+ Value = [System.Net.WebUtility]::HtmlEncode($Value)
+ }
+}
+
+function Add-PodeWebDatalistOption {
+ [CmdletBinding(DefaultParameterSetName = 'Name')]
+ param(
+ [Parameter(Mandatory = $true, ParameterSetName = 'Name')]
+ [string]
+ $Name,
+
+ [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
+ [string]
+ $Id,
+
+ [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
+ [hashtable[]]
+ $Option,
+
+ [switch]
+ $NoAutoSelect
+ )
+
+ begin {
+ $items = @()
+ }
+
+ process {
+ $items += $Option
+ }
+
+ end {
+ # ensure options are only of type option
+ if (!(Test-PodeWebContent -Content $items -ComponentType Element -ObjectType 'Option')) {
+ throw 'A Datalist can only contain Options'
+ }
+
+ Send-PodeWebAction -Value @{
+ Operation = 'Add'
+ ObjectType = 'Datalist'
+ Name = $Name
+ ID = $Id
+ Options = $items
+ NoAutoSelect = $NoAutoSelect.IsPresent
+ }
+ }
+}
+
+function Remove-PodeWebDatalistOption {
+ [CmdletBinding(DefaultParameterSetName = 'Name')]
+ param(
+ [Parameter(Mandatory = $true, ParameterSetName = 'Name')]
+ [string]
+ $Name,
+
+ [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
+ [string]
+ $Id,
+
+ [Parameter(ValueFromPipeline = $true)]
+ [string[]]
+ $OptionName,
+
+ [switch]
+ $NoAutoSelect
+ )
+
+ Send-PodeWebAction -Value @{
+ Operation = 'Remove'
+ ObjectType = 'Datalist'
+ Name = $Name
+ ID = $Id
+ OptionName = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'OptionName' -Value $OptionName)
+ NoAutoSelect = $NoAutoSelect.IsPresent
+ }
+}
+
+function Update-PodeWebDatalist {
+ [CmdletBinding(DefaultParameterSetName = 'Name')]
+ param(
+ [Parameter(Mandatory = $true, ParameterSetName = 'Name')]
+ [string]
+ $Name,
+
+ [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
+ [string]
+ $Id,
+
+ [Parameter(ValueFromPipeline = $true)]
+ [hashtable[]]
+ $Options,
+
+ [switch]
+ $ReadOnly,
+
+ [switch]
+ $Disabled,
+
+ [switch]
+ $NoAutoSelect
+ )
+
+ begin {
+ $items = @()
+ }
+
+ process {
+ $items += $Options
+ }
+
+ end {
+ if (!(Test-PodeWebContent -Content $items -ComponentType Element -ObjectType 'Option')) {
+ throw 'A Datalist can only contain Options'
+ }
+
+ Send-PodeWebAction -Value @{
+ Operation = 'Update'
+ ObjectType = 'Datalist'
+ Name = $Name
+ ID = $Id
+ Options = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'Options' -Value $items)
+ ReadOnly = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'ReadOnly' -Value $ReadOnly.IsPresent)
+ Disabled = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'Disabled' -Value $Disabled.IsPresent)
+ NoAutoSelect = (Test-PodeWebParameter -Parameters $PSBoundParameters -Name 'NoAutoSelect' -Value $NoAutoSelect.IsPresent)
+ }
+ }
+}
+
+function Clear-PodeWebDatalist {
+ [CmdletBinding(DefaultParameterSetName = 'Name')]
+ param(
+ [Parameter(Mandatory = $true, ParameterSetName = 'Name')]
+ [string]
+ $Name,
+
+ [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
+ [string]
+ $Id
+ )
+
+ Send-PodeWebAction -Value @{
+ Operation = 'Clear'
+ ObjectType = 'Datalist'
+ Name = $Name
+ ID = $Id
+ }
+}
+
+function Sync-PodeWebDatalist {
+ [CmdletBinding(DefaultParameterSetName = 'Name')]
+ param(
+ [Parameter(Mandatory = $true, ParameterSetName = 'Name')]
+ [string]
+ $Name,
+
+ [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
+ [string]
+ $Id
+ )
+
+ Send-PodeWebAction -Value @{
+ Operation = 'Sync'
+ ObjectType = 'Datalist'
+ Name = $Name
+ ID = $Id
+ }
+}
+
function Update-PodeWebBadge {
[CmdletBinding()]
param(
diff --git a/src/Public/Elements.ps1 b/src/Public/Elements.ps1
index 2d5a0566..993320bd 100644
--- a/src/Public/Elements.ps1
+++ b/src/Public/Elements.ps1
@@ -379,6 +379,10 @@ function New-PodeWebCheckbox {
[string[]]
$DisplayOptions,
+ [Parameter()]
+ [string]
+ $HelpText,
+
[Parameter(ParameterSetName = 'Multiple')]
[switch]
$Inline,
@@ -415,6 +419,7 @@ function New-PodeWebCheckbox {
ID = $Id
Options = @($Options)
DisplayOptions = @(Protect-PodeWebValues -Value $DisplayOptions -Default $Options -EqualCount -Encode)
+ HelpText = [System.Net.WebUtility]::HtmlEncode($HelpText)
Inline = $Inline.IsPresent
AsSwitch = $AsSwitch.IsPresent
Checked = $Checked.IsPresent
@@ -446,6 +451,10 @@ function New-PodeWebRadio {
[string[]]
$DisplayOptions,
+ [Parameter()]
+ [string]
+ $HelpText,
+
[switch]
$Inline,
@@ -471,6 +480,7 @@ function New-PodeWebRadio {
ID = $Id
Options = @($Options)
DisplayOptions = @(Protect-PodeWebValues -Value $DisplayOptions -Default $Options -EqualCount -Encode)
+ HelpText = [System.Net.WebUtility]::HtmlEncode($HelpText)
Inline = $Inline.IsPresent
Disabled = $Disabled.IsPresent
Required = $Required.IsPresent
@@ -493,13 +503,9 @@ function New-PodeWebSelect {
$Id,
[Parameter(ParameterSetName = 'Options')]
- [string[]]
+ [hashtable[]]
$Options,
- [Parameter(ParameterSetName = 'Options')]
- [string[]]
- $DisplayOptions,
-
[Parameter(ParameterSetName = 'ScriptBlock')]
[scriptblock]
$ScriptBlock,
@@ -509,10 +515,7 @@ function New-PodeWebSelect {
$ArgumentList,
[Parameter()]
- [string[]]
- $SelectedValue,
-
- [Parameter()]
+ [ValidateRange(1, [int]::MaxValue)]
[int]
$Size = 4,
@@ -532,6 +535,10 @@ function New-PodeWebSelect {
[string]
$AppendIcon,
+ [Parameter()]
+ [string]
+ $HelpText,
+
[switch]
$Multiple,
@@ -545,16 +552,41 @@ function New-PodeWebSelect {
$HideName
)
- if (!$Multiple.IsPresent -and $SelectedValue.Length -ge 2) {
- throw 'Multiple selected values require -Multiple switch'
+ # ensure options are only of type option or option-group
+ if (!(Test-PodeWebContent -Content $Options -ComponentType Element -ObjectType 'Option', 'Option-Group')) {
+ throw 'A Select can only contain Options or Option Groups'
}
- $Id = Get-PodeWebElementId -Tag Select -Id $Id -Name $Name
+ # only allow multiple selected values if -Multiple is set
+ if (!$Multiple) {
+ $selectedCount = 0
+
+ foreach ($option in $Options) {
+ if ($option.Selected) {
+ $selectedCount++
+ continue
+ }
+
+ if ($option.ObjectType -ine 'Option-Group') {
+ continue
+ }
- if ($Size -le 0) {
- $Size = 4
+ foreach ($groupOption in $option.Options) {
+ if ($groupOption.Selected) {
+ $selectedCount++
+ }
+ }
+ }
+
+ if ($selectedCount -ge 2) {
+ throw 'Multiple selected options require -Multiple switch'
+ }
}
+ # generate an ID
+ $Id = Get-PodeWebElementId -Tag Select -Id $Id -Name $Name
+
+ # build element
$element = @{
Operation = 'New'
ComponentType = 'Element'
@@ -563,12 +595,11 @@ function New-PodeWebSelect {
DisplayName = (Protect-PodeWebValue -Value $DisplayName -Default $Name -Encode)
HideName = $HideName.IsPresent
ID = $Id
- Options = @($Options)
- DisplayOptions = @(Protect-PodeWebValues -Value $DisplayOptions -Default $Options -EqualCount -Encode)
+ Options = $Options
IsDynamic = ($null -ne $ScriptBlock)
- SelectedValue = $SelectedValue
Multiple = $Multiple.IsPresent
Size = $Size
+ HelpText = [System.Net.WebUtility]::HtmlEncode($HelpText)
Prepend = @{
Enabled = (![string]::IsNullOrWhiteSpace($PrependText) -or ![string]::IsNullOrWhiteSpace($PrependIcon))
Text = $PrependText
@@ -636,7 +667,203 @@ function New-PodeWebSelect {
}
if ($result.Length -gt 0) {
- $result = ($result | Update-PodeWebSelect -Id $ElementData.ID)
+ $result = $result |
+ ConvertTo-PodeWebOption |
+ Update-PodeWebSelect -Id $ElementData.ID
+ }
+
+ $result = Join-PodeWebDynamicOutput -Wrapped $wrapped -Output $result
+
+ if (($null -ne $result) -and ($result.Length -gt 0)) {
+ Write-PodeJsonResponse -Value $result
+ }
+
+ $global:ElementData = $null
+ $global:ParentData = $null
+ }
+ }
+
+ return $element
+}
+
+function New-PodeWebDatalist {
+ [CmdletBinding(DefaultParameterSetName = 'Options')]
+ param(
+ [Parameter(Mandatory = $true)]
+ [string]
+ $Name,
+
+ [Parameter()]
+ [string]
+ $DisplayName,
+
+ [Parameter()]
+ [string]
+ $Id,
+
+ [Parameter(ParameterSetName = 'Options')]
+ [hashtable[]]
+ $Options,
+
+ [Parameter(ParameterSetName = 'ScriptBlock')]
+ [scriptblock]
+ $ScriptBlock,
+
+ [Parameter(ParameterSetName = 'ScriptBlock')]
+ [object[]]
+ $ArgumentList,
+
+ [Parameter()]
+ [string]
+ $Placeholder,
+
+ [Parameter()]
+ [string]
+ $Width = 100,
+
+ [Parameter()]
+ [string]
+ $PrependText,
+
+ [Parameter()]
+ [string]
+ $PrependIcon,
+
+ [Parameter()]
+ [string]
+ $AppendText,
+
+ [Parameter()]
+ [string]
+ $AppendIcon,
+
+ [Parameter()]
+ [string]
+ $HelpText,
+
+ [switch]
+ $ReadOnly,
+
+ [switch]
+ $Required,
+
+ [switch]
+ $Disabled,
+
+ [switch]
+ $HideName,
+
+ [switch]
+ $NoAutoSelect
+ )
+
+ # ensure options are only of type option
+ if (!(Test-PodeWebContent -Content $Options -ComponentType Element -ObjectType 'Option')) {
+ throw 'A Datalist can only contain Options'
+ }
+
+ # error if multiple selected values
+ $selectedCount = 0
+
+ foreach ($option in $Options) {
+ if ($option.Selected) {
+ $selectedCount++
+ }
+ }
+
+ if ($selectedCount -ge 2) {
+ throw 'Datalist cannot have multiple selected options'
+ }
+
+ # generate an ID
+ $Id = Get-PodeWebElementId -Tag Datalist -Id $Id -Name $Name
+
+ # build element
+ $element = @{
+ Operation = 'New'
+ ComponentType = 'Element'
+ ObjectType = 'Datalist'
+ Name = $Name
+ DisplayName = (Protect-PodeWebValue -Value $DisplayName -Default $Name -Encode)
+ HideName = $HideName.IsPresent
+ ID = $Id
+ Options = $Options
+ IsDynamic = ($null -ne $ScriptBlock)
+ Placeholder = $Placeholder
+ Width = (ConvertTo-PodeWebSize -Value $Width -Default 'auto' -Type '%')
+ HelpText = [System.Net.WebUtility]::HtmlEncode($HelpText)
+ Prepend = @{
+ Enabled = (![string]::IsNullOrWhiteSpace($PrependText) -or ![string]::IsNullOrWhiteSpace($PrependIcon))
+ Text = $PrependText
+ Icon = $PrependIcon
+ }
+ Append = @{
+ Enabled = (![string]::IsNullOrWhiteSpace($AppendText) -or ![string]::IsNullOrWhiteSpace($AppendIcon))
+ Text = $AppendText
+ Icon = $AppendIcon
+ }
+ NoAuthentication = $NoAuthentication.IsPresent
+ NoAutoSelect = $NoAutoSelect.IsPresent
+ ReadOnly = $ReadOnly.IsPresent
+ Required = $Required.IsPresent
+ Disabled = $Disabled.IsPresent
+ }
+
+ $routePath = "/pode.web-dynamic/elements/datalist/$($Id)/options"
+ if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) {
+ # check for scoped vars
+ $ScriptBlock, $usingVars = Convert-PodeScopedVariables -ScriptBlock $ScriptBlock -PSSession $PSCmdlet.SessionState
+ $elementLogic = @{
+ ScriptBlock = $ScriptBlock
+ UsingVariables = $usingVars
+ }
+
+ $auth = $null
+ if (!$NoAuthentication -and !$PageData.NoAuthentication) {
+ $auth = (Get-PodeWebState -Name 'auth')
+ }
+
+ if (Test-PodeIsEmpty $EndpointName) {
+ $EndpointName = Get-PodeWebState -Name 'endpoint-name'
+ }
+
+ $argList = @(
+ @{ Data = $ArgumentList },
+ $element,
+ $ElementData,
+ $elementLogic
+ )
+
+ Add-PodeRoute -Method Post -Path $routePath -Authentication $auth -ArgumentList $argList -EndpointName $EndpointName -ScriptBlock {
+ param($Data, $Element, $Parent, $Logic)
+ $global:ElementData = $Element
+ $global:ParentData = $Parent
+ Set-PodeWebMetadata
+
+ $result = @(Invoke-PodeWebScriptBlock -Logic $Logic -Arguments $Data.Data)
+
+ $wrapped = $null
+ if (Test-PodeWebActionsAsync) {
+ if ($result.Length -gt 0) {
+ if ($null -eq $result[0]) {
+ $result = @()
+ }
+
+ $wrapped, $result = Split-PodeWebDynamicOutput -Output $result
+ }
+ }
+ else {
+ if ($null -eq $result) {
+ $result = @()
+ }
+
+ $wrapped, $result = Split-PodeWebDynamicOutput -Output $result
+ }
+
+ if ($result.Length -gt 0) {
+ $result = $result |
+ ConvertTo-PodeWebOption |
+ Update-PodeWebDatalist -Id $ElementData.ID
}
$result = Join-PodeWebDynamicOutput -Wrapped $wrapped -Output $result
@@ -653,6 +880,101 @@ function New-PodeWebSelect {
return $element
}
+function New-PodeWebOptionGroup {
+ [CmdletBinding()]
+ param(
+ [Parameter(Mandatory = $true)]
+ [string]
+ $Name,
+
+ [Parameter()]
+ [string]
+ $DisplayName,
+
+ [Parameter(Mandatory = $true)]
+ [hashtable[]]
+ $Options,
+
+ [switch]
+ $Disabled
+ )
+
+ if (!(Test-PodeWebContent -Content $Options -ComponentType Element -ObjectType Option)) {
+ throw 'An Option Group can only contain Options'
+ }
+
+ return @{
+ Operation = 'New'
+ ComponentType = 'Element'
+ ObjectType = 'Option-Group'
+ Name = (Protect-PodeWebValue -Value $Name -Encode)
+ DisplayName = (Protect-PodeWebValue -Value $DisplayName -Default $Name -Encode)
+ Options = $Options
+ Disabled = $Disabled.IsPresent
+ }
+}
+
+function New-PodeWebOption {
+ [CmdletBinding()]
+ param(
+ [Parameter(Mandatory = $true)]
+ [string]
+ $Name,
+
+ [Parameter()]
+ [string]
+ $DisplayName,
+
+ [Parameter()]
+ [string]
+ $Label,
+
+ [switch]
+ $Disabled,
+
+ [switch]
+ $Selected
+ )
+
+ return @{
+ Operation = 'New'
+ ComponentType = 'Element'
+ ObjectType = 'Option'
+ Name = $Name
+ DisplayName = (Protect-PodeWebValue -Value $DisplayName -Default $Name -Encode)
+ Label = (Protect-PodeWebValue -Value $Label -Encode)
+ Disabled = $Disabled.IsPresent
+ Selected = $Selected.IsPresent
+ }
+}
+
+function ConvertTo-PodeWebOption {
+ [CmdletBinding()]
+ param(
+ [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
+ [string[]]
+ $InputObject,
+
+ [Parameter()]
+ [string[]]
+ $SelectedOption
+ )
+
+ begin {
+ $items = @()
+ }
+
+ process {
+ $items += $InputObject
+ }
+
+ end {
+ foreach ($item in $items) {
+ New-PodeWebOption -Name $item -Selected:($item -iin $SelectedOption)
+ }
+ }
+}
+
function New-PodeWebRange {
[CmdletBinding()]
param(
@@ -685,6 +1007,10 @@ function New-PodeWebRange {
[double]
$Step = 1.0,
+ [Parameter()]
+ [string]
+ $HelpText,
+
[switch]
$Disabled,
@@ -737,6 +1063,7 @@ function New-PodeWebRange {
Min = $Min
Max = $Max
Step = $Step
+ HelpText = [System.Net.WebUtility]::HtmlEncode($HelpText)
Disabled = $Disabled.IsPresent
ShowValue = $ShowValue.IsPresent
Required = $Required.IsPresent
diff --git a/src/Public/Pages.ps1 b/src/Public/Pages.ps1
index 84bcf8cc..318e107b 100644
--- a/src/Public/Pages.ps1
+++ b/src/Public/Pages.ps1
@@ -921,11 +921,15 @@ function ConvertTo-PodeWebPage {
if ($param.Attributes.TypeId.Name -icontains 'ValidateSetAttribute') {
$values = ($param.Attributes | Where-Object { $_.TypeId.Name -ieq 'ValidateSetAttribute' }).ValidValues
- New-PodeWebSelect -Name "$($name)_$($param.Name)" -DisplayName $param.Name -Options $values -SelectedValue $default -Multiple:$multiple
+ New-PodeWebSelect -Name "$($name)_$($param.Name)" -DisplayName $param.Name -Multiple:$multiple -Options @(
+ $values | ConvertTo-PodeWebOption -SelectedValue $default
+ )
}
elseif ($param.ParameterType.BaseType.Name -ieq 'enum') {
$values = [enum]::GetValues($param.ParameterType)
- New-PodeWebSelect -Name "$($name)_$($param.Name)" -DisplayName $param.Name -Options $values -SelectedValue $default -Multiple:$multiple
+ New-PodeWebSelect -Name "$($name)_$($param.Name)" -DisplayName $param.Name -Multiple:$multiple -Options @(
+ $values | ConvertTo-PodeWebOption -SelectedValue $default
+ )
}
else {
New-PodeWebTextbox -Name "$($name)_$($param.Name)" -DisplayName $param.Name -Value $default
diff --git a/src/Templates/Public/scripts/templates.js b/src/Templates/Public/scripts/templates.js
index 2a2cc5a2..4099387f 100644
--- a/src/Templates/Public/scripts/templates.js
+++ b/src/Templates/Public/scripts/templates.js
@@ -859,7 +859,6 @@ class PodeElement {
// check focus state
if (obj.focusable && (evt == 'focus' || evt == 'focusout') && obj.previouslyFocused === obj.focused) {
skip = true;
- console.log(`focus: ${obj.focused}, skip event ${evt}`);
}
// stop propagation/prevent default
@@ -1680,7 +1679,7 @@ class PodeFormElement extends PodeContentElement {
// help text
if (this.help.enabled && this.help.text) {
- html += `${this.help.text}`;
+ html += `${this.help.text}`;
}
// are we in a form?
@@ -1774,6 +1773,53 @@ class PodeFormElement extends PodeContentElement {
}
}
+class PodeFormOptionElement extends PodeFormElement {
+ constructor(data, sender, opts) {
+ super(data, sender, opts);
+ }
+
+ buildOptions(options) {
+ var html = '';
+
+ convertToArray(options).forEach((opt) => {
+ if (opt.Options) {
+ html += this.buildGroup(opt);
+ }
+ else {
+ html += this.buildOption(opt);
+ }
+ });
+
+ return html;
+ }
+
+ buildOption(option) {
+ var label = option.Label ? ` label='${option.Label}'` : '';
+
+ return ``;
+ }
+
+ buildGroup(group) {
+ var html = ``;
+ return html;
+ }
+}
+
class PodeFormMultiElement extends PodeFormElement {
constructor(data, sender, opts) {
super(data, sender, opts);
@@ -5315,35 +5361,21 @@ class PodeHidden extends PodeFormElement {
}
PodeElementFactory.setClass(PodeHidden);
-class PodeSelect extends PodeFormElement {
+class PodeSelect extends PodeFormOptionElement {
static type = 'select';
constructor(data, sender, opts) {
super(data, sender, opts);
- this.multiSelect = data.Multiple ?? false;
+ this.multiple = data.Multiple ?? false;
}
new(data, sender, opts) {
- var multiple = this.multiSelect ? `multiple size='${data.Size ?? 1}'` : '';
-
- var selectedValue = convertToArray(data.SelectedValue);
- if (!this.multiSelect && selectedValue.length >= 2) {
- selectedValue = [selectedValue[0]];
- }
+ var multiple = this.multiple ? `multiple size='${data.Size ?? 1}'` : '';
var options = '';
- data.DisplayOptions = convertToArray(data.DisplayOptions);
- convertToArray(data.Options).forEach((opt, index) => {
- if (!opt) {
- return;
- }
-
- options += ``;
- });
+ if (data.Options) {
+ options = this.buildOptions(data.Options);
+ }
return `