Product: PowerShell Universal
Version: 5.1.0
I apologize in advance for the long text, there is just no way i can ask the question without going over my issue.
I have been studying Powershell Universal for a few weeks. Below are basically my notes during my study. Now my issue is with Forms and Form validations.
You can do this in different ways.
TL;DR What is the best way to 1) create a form and 2) to validate it
First, lets go over my understanding of forms within PSU.
Forms in PSU
It looks like there are 2 methods/ways to create a form, one gives more control than the other.
Method 1 : New-UDForm
New-UDForm
→ seems to create a submit button that we cannot really manage all that well (disabling seems an issue). In previous versions of PSU this was know asNew-UDInput.
New-UDForm -Content {
New-UDTextbox -Id 'txtTextField'
New-UDCheckbox -Id 'chkCheckbox'
} -OnSubmit {
Show-UDToast -Message $EventData.txtTextField
Show-UDToast -Message $EventData.chkCheckbox
}
The -OnSubmit
automatically adds a submit button.
This is great for easy forms but harder to do when you want to control the submit button (e.g with validation rules).
Method 2 : Manually build your form
New-UDApp -Content {
New-UDCard -Title "Create Shared Mailbox" -Content {
New-UDSelect -Id 'selectOU' -Label 'OU' -Option {
New-UDSelectOption -Name 'CMMC' -Value 'CMMC'
New-UDSelectOption -Name 'CM' -Value 'CM'
New-UDSelectOption -Name 'MC' -Value 'MC'
}
New-UDTextbox -Id 'txtDisplayName' -Label 'Display Name' -Placeholder 'Enter Display Name'
New-UDButton -Id 'SubmitButton' -Text 'Submit' -OnClick {
$OU = (Get-UDElement -Id 'selectOU').value
$DisplayName = (Get-UDElement -Id 'txtDisplayName').value
if ($OU -and $DisplayName)
{
Show-UDToast -Message "OU: $OU, Display Name: $DisplayName" -Duration 4000
}
else
{
Show-UDToast -Message "Please fill in all fields!" -Severity error
}
}
}
}
This is its most basic form and looks like:
$Eventdata
When you use the 1st method, $EventData
is available for you to use.
This doesn’t seem to be the case when you manually build the form.
You then have to capture your individual components, based on their ID.
E.g $OU = (Get-UDElement -Id 'selectOU').value
Validating forms
You can do it in 2 ways.
1) Validation at (input)-field level
New-UDColumn -Size 2 -Content {
New-UDTextbox -Id 'txtDisplayName' -Label 'Displayname' -Placeholder 'CM - Koerswedstrijd De zeven kamp' -HelperText 'Please respect naming conventions' -OnValidate {
# Only validate if there's actual input
if ($Eventdata) { if ($Eventdata -notmatch '\w+ - \w+') { New-UDValidationResult -ValidationError '*Displayname does not contain a space.' } else { New-UDValidationResult -Valid } } else { New-UDValidationResult -Valid }
} -OnChange {
Sync-UDElement -Id 'dynamicContent'
}
}
It is my understanding that #$Eventdata in this case seems to function like $this
.
If this filed has data, … .
If a #New-UDValidationResult-ValidationError
gets created, the submit button gets disabled automatically.
A similar approach would be:
New-UDForm -Content {
New-UDTextbox -Id 'txtUPN' -Label 'UserPrincipalName' -Placeholder 'UPN'
} -OnValidate {
$UPN = (Get-UDElement -Id 'txtUPN').value -replace '\s', ''
# Only validate if there's actual input
if (-not [string]::IsNullOrWhiteSpace($UPN)) {
$Exists = get-aduser -Filter { UserPrincipalName -like $UPN }
if ($Exists) {
New-UDValidationResult -ValidationError "*$($Exists.Name) already exists"
return $false # Prevent form submission
}
}
New-UDValidationResult -Valid # Allow submission when no input or no existing user
} -OnSubmit {
# Your submission logic here
}
The problem with this approach is that if you have 2 validations on 2 individual fields, they will undo the validation of the other.
-
You check the UPN and another field, both fail so the submit button is disabled.
-
You change the UPN to get passed the check, the button enables.
→ Wrong because all validation rules haven’t been met yet! Our
OtherField
is still NOK.
2) Validation (before) submit on the entire form level
This works in a similar way. The error message however, is no longer displayed inline but just above the submit button.
We can get inline error mesages like this.
**
The problem now is, the validation check is not reliable. Sometimes it disables it but on other occasions it doesn’t (even though it should) and vice versa.
**
New-UDForm -Content {
New-UDTextbox -Id 'txtUPN' -Label 'UserPrincipalName' -Placeholder 'UPN'
New-UDTextbox -Id 'txtOtherField' -Label 'Other Field' -Placeholder 'Other Input'
} -OnValidate {
$validationResults = @()
# Validate UPN
$UPN = (Get-UDElement -Id 'txtUPN').value -replace '\s', ''
if (-not [string]::IsNullOrWhiteSpace($UPN)) {
$Exists = get-aduser -Filter { UserPrincipalName -like $UPN }
if ($Exists) {
$validationResults += (New-UDValidationResult -ValidationError "*$($Exists.Name) already exists")
}
}
# Validate Other Field
$OtherField = (Get-UDElement -Id 'txtOtherField').value -replace '\s', ''
# Add your specific validation for the other field here
if ($OtherField -eq 'jef') {
$validationResults += (New-UDValidationResult -ValidationError "Other field cannot be 'jef'")
}
# If any validation errors, return false and show errors
if ($validationResults.Count -gt 0) {
# This is the key change - passing all collected validation results
return $validationResults
}
# If no errors, return valid
New-UDValidationResult -Valid
return $true
} -OnSubmit {
# Your submission logic here
}
}
New-UDPage -Url "/CreateSharedMailbox" -Name "CreateSharedMailbox" -Content {
New-UDForm -Content {
New-UDTextbox -Id 'txtUPN' -Label 'UserPrincipalName' -Placeholder 'UPN' -OnValidate {
$UPN = (Get-UDElement -Id 'txtUPN').value -replace '\s', ''
# Only validate if there's actual input
$Exists = get-aduser -Filter { UserPrincipalName -like $UPN }
if ($Exists) {
New-UDValidationResult -ValidationError "*$($Exists.Name) already exists"
return $false # Prevent form submission
}else{return $true}
}
New-UDTextbox -Id 'txtOtherField' -Label 'Other Field' -Placeholder 'Other Input' -OnValidate {
# Validate Other Field
$OtherField = (Get-UDElement -Id 'txtOtherField').value -replace '\s', ''
if ($OtherField -eq 'jef') {
New-UDValidationResult -ValidationError "Other field cannot be 'jef'"
return $false # Prevent form submission
}else{return $true}
}
} -OnValidate {
# Aggregate validation from individual fields
$UPNElement = Get-UDElement -Id 'txtUPN'
$OtherFieldElement = Get-UDElement -Id 'txtOtherField'
# Check if either field has a validation error
if ($UPNElement.ValidationError -or $OtherFieldElement.ValidationError) {
return $false
}else{
New-UDValidationResult -Valid
return $true
}
} -OnSubmit {
# Your submission logic here
}
}
Notes
The OnValidate
on the form level, seems to be triggered during onPageLoad
and on the onChange
event of every individual field.
Since the validation gets triggered when the page gets loaded, it is important to prevent error messages from showing in this initial stage.