Skip to content

Commit

Permalink
Merge pull request #586 from Badgerati/fix_modal_txtbox
Browse files Browse the repository at this point in the history
Fixes a bug preventing textboxes in Modals from working; Fixes a bug preventing URL Buttons from working
  • Loading branch information
Badgerati committed Jun 16, 2024
2 parents 7d02dc8 + 357bf9e commit 2628e90
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 54 deletions.
10 changes: 5 additions & 5 deletions docs/Tutorials/Elements/Modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
| ------- | --- |
| Events | No |

A modal is an element that renders on top of all other content on your web page - such as prompts to confirm information before performing an action, or a quick edit dialog.
A modal is an element that renders on top of all other content on your web page - such as prompts to confirm information before acting, or a quick edit dialog.

A modal takes an array of elements via `-Content`.

## Usage

To create a modal element you use [`New-PodeWebModal`](../../../Functions/Elements/New-PodeWebModal), supplying a `-Name` and any `-Content`. The modal will then be on the page, but will be hidden until required. You can also supply a `-ScriptBlock` with logic to be invoked when the modal's Submit button is clicked.
To create a modal element you use [`New-PodeWebModal`](../../../Functions/Elements/New-PodeWebModal), supplying a `-Name` and any `-Content`. The modal will then be on the page but will be hidden until required. You can also supply a `-ScriptBlock` with logic to be invoked when the modal's Submit button is clicked.

To show the modal, you can use the action [`Show-PodeWebModal`](../../../Functions/Actions/Show-PodeWebModal), and supply the `-Name` of the modal to show. You can populate elements within the modal just prior to it being shown by using `-Actions`; this takes more actions to invoke such as [`Update-PodeWebCheckbox`](../../../Functions/Actions/Update-PodeWebCheckbox) and [`Update-PodeWebTextbox`](../../../Functions/Actions/Update-PodeWebTextbox), which reference elements within the modal.

Expand All @@ -20,7 +20,7 @@ There's also [`Hide-PodeWebModal`](../../../Functions/Actions/Hide-PodeWebModal)

### Confirmation

The example below renders a table of services on the current computer. When the "stop" button/icon is clicked, the name of the service on that row (the `-DataColumn`) is passed to the button, and in-turn that supplies the service name to [`Show-PodeWebModal`](../../../Functions/Actions/Show-PodeWebModal). The modal asks if the user wants to stop the service, and on Submit it will stop the service and hide the modal:
The example below renders a table of services on the current computer. When the "stop" button/icon is clicked, the name of the service on that row (the `-DataColumn`) is passed to the button, and in turn that supplies the service name to [`Show-PodeWebModal`](../../../Functions/Actions/Show-PodeWebModal). The modal asks if the user wants to stop the service, and on Submit it will stop the service and hide the modal:

```powershell
New-PodeWebCard -Content @(
Expand Down Expand Up @@ -62,7 +62,7 @@ Which would look like below:

To use a form in your modal, you need to supply `-AsForm` to [`New-PodeWebModal`](../../../Functions/Elements/New-PodeWebModal).

The example below again renders a table of services on the current computer. But this time there's an edit button to alter the Start-Up type of a service. When the "edit" button/icon is clicked, the name of the service on that row (the `-DataColumn`) is passed to the button, and in-turn that supplies the service name to [`Show-PodeWebModal`](../../../Functions/Actions/Show-PodeWebModal). The modal then shows a form with a select input to change the service's Start-Up type:
The example below again renders a table of services on the current computer. But this time there's an edit button to alter the Start-Up type of a service. When the "edit" button/icon is clicked, the name of the service on that row (the `-DataColumn`) is passed to the button, and in turn that supplies the service name to [`Show-PodeWebModal`](../../../Functions/Actions/Show-PodeWebModal). The modal then shows a form with a select input to change the service's Start-Up type:

```powershell
New-PodeWebCard -Content @(
Expand All @@ -89,7 +89,7 @@ New-PodeWebModal -Name 'Edit Service' -AsForm -Content @(
New-PodeWebSelect -Name 'StartType' -Options Manual, Automatic, Disabled
) -ScriptBlock {
Get-Service -Name $WebEvent.Data.Value | Set-Service -StartType $WebEvent.Data.StartType | Out-Null
Show-PodeWebToast -Message "$($WebEvent.Data.Value) editted"
Show-PodeWebToast -Message "$($WebEvent.Data.Value) edited"
Sync-PodeWebTable -Name 'Services'
Hide-PodeWebModal
}
Expand Down
2 changes: 1 addition & 1 deletion examples/links.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Start-PodeServer -Browse {

New-PodeWebCard -Name 'Update Link' -Content @(
New-PodeWebButtonGroup -Buttons @(
New-PodeWebButton -Name 'Update to Goole' -ScriptBlock {
New-PodeWebButton -Name 'Update to Google' -ScriptBlock {
Update-PodeWebLink -Id 'link' -Value 'Google' -Url 'https://www.google.com'
}
New-PodeWebButton -Name 'Update to DuckDuckGo' -ScriptBlock {
Expand Down
44 changes: 44 additions & 0 deletions examples/modals.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Import-Module Pode -MaximumVersion 2.99.99 -Force
Import-Module ..\src\Pode.Web.psm1 -Force

Start-PodeServer -Browse {
# add a simple endpoint
Add-PodeEndpoint -Address localhost -Port 8090 -Protocol Http
New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging

# set the use of templates, and set a login page
Use-PodeWebTemplates -Title 'Modals Example' -Theme Dark

# home page with link togglging
Add-PodeWebPage -Name 'Home' -Path '/' -HomePage -Title 'Homepage' -ScriptBlock {
# modal 1 - form
New-PodeWebModal -Name 'Form Modal' -AsForm -Content @(
New-PodeWebTextbox -Name 'Name1' -Type Text
New-PodeWebTextbox -Name 'Comment1' -Multiline
) -ScriptBlock {
Show-PodeWebToast -Title $WebEvent.Data.Name1 -Message $WebEvent.Data.Comment1
Hide-PodeWebModal
}

# modal 2 - no form
New-PodeWebModal -Name 'Normal Modal' -Content @(
New-PodeWebTextbox -Name 'Name2' -Type Text
New-PodeWebTextbox -Name 'Comment2' -Multiline
) -ScriptBlock {
Show-PodeWebToast -Title $WebEvent.Data.Name2 -Message $WebEvent.Data.Comment2
Hide-PodeWebModal
}

# buttons to show modals
New-PodeWebCard -Name 'Show Modals' -Content @(
New-PodeWebButtonGroup -Buttons @(
New-PodeWebButton -Name 'Show Form Modal' -ScriptBlock {
Show-PodeWebModal -Name 'Form Modal'
}
New-PodeWebButton -Name 'Show Normal Modal' -ScriptBlock {
Show-PodeWebModal -Name 'Normal Modal'
}
)
)
}
}
20 changes: 10 additions & 10 deletions src/Public/Elements.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ function New-PodeWebSelect {
Disabled = $Disabled.IsPresent
}

$routePath = "/pode.web-dynamic/elements/select/$($Id)"
$routePath = "/pode.web-dynamic/elements/select/$($Id)/options"
if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) {
# check for scoped vars
$ScriptBlock, $usingVars = Convert-PodeScopedVariables -ScriptBlock $ScriptBlock -PSSession $PSCmdlet.SessionState
Expand Down Expand Up @@ -1458,7 +1458,7 @@ function New-PodeWebButton {
Disabled = $Disabled.IsPresent
}

$routePath = "/pode.web-dynamic/elements/button/$($Id)"
$routePath = "/pode.web-dynamic/elements/button/$($Id)/click"
if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) {
# check for scoped vars
$ScriptBlock, $usingVars = Convert-PodeScopedVariables -ScriptBlock $ScriptBlock -PSSession $PSCmdlet.SessionState
Expand Down Expand Up @@ -1952,7 +1952,7 @@ function New-PodeWebChart {
Colours = $Colours
}

$routePath = "/pode.web-dynamic/elements/chart/$($Id)"
$routePath = "/pode.web-dynamic/elements/chart/$($Id)/data"
if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) {
# check for scoped vars
$ScriptBlock, $usingVars = Convert-PodeScopedVariables -ScriptBlock $ScriptBlock -PSSession $PSCmdlet.SessionState
Expand Down Expand Up @@ -2290,7 +2290,7 @@ function New-PodeWebTable {
}

# main table data script
$routePath = "/pode.web-dynamic/elements/table/$($Id)"
$routePath = "/pode.web-dynamic/elements/table/$($Id)/data"
$buildRoute = (($null -ne $ScriptBlock) -or ![string]::IsNullOrWhiteSpace($CsvFilePath))

if ($buildRoute -and !(Test-PodeWebRoute -Path $routePath)) {
Expand Down Expand Up @@ -2730,7 +2730,7 @@ function New-PodeWebForm {

# generate ID
$Id = Get-PodeWebElementId -Tag Form -Id $Id -Name $Name
$routePath = "/pode.web-dynamic/elements/form/$($Id)"
$routePath = "/pode.web-dynamic/elements/form/$($Id)/submit"

$element = @{
Operation = 'New'
Expand Down Expand Up @@ -2857,7 +2857,7 @@ function New-PodeWebTimer {
UsingVariables = $usingVars
}

$routePath = "/pode.web-dynamic/elements/timer/$($Id)"
$routePath = "/pode.web-dynamic/elements/timer/$($Id)/trigger"
if (!(Test-PodeWebRoute -Path $routePath)) {
$auth = $null
if (!$NoAuthentication -and !$PageData.NoAuthentication) {
Expand Down Expand Up @@ -3003,7 +3003,7 @@ function New-PodeWebTile {
}

# main route to load tile value
$routePath = "/pode.web-dynamic/elements/tile/$($Id)"
$routePath = "/pode.web-dynamic/elements/tile/$($Id)/data"
if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) {
# check for scoped vars
$ScriptBlock, $usingVars = Convert-PodeScopedVariables -ScriptBlock $ScriptBlock -PSSession $PSCmdlet.SessionState
Expand Down Expand Up @@ -3809,7 +3809,7 @@ function New-PodeWebModal {
# generate ID
$Id = Get-PodeWebElementId -Tag Modal -Id $Id -Name $Name

$routePath = "/pode.web-dynamic/elements/modal/$($Id)"
$routePath = "/pode.web-dynamic/elements/modal/$($Id)/submit"
if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) {
# check for scoped vars
$ScriptBlock, $usingVars = Convert-PodeScopedVariables -ScriptBlock $ScriptBlock -PSSession $PSCmdlet.SessionState
Expand Down Expand Up @@ -3998,7 +3998,7 @@ function New-PodeWebSteps {
$Id = Get-PodeWebElementId -Tag Steps -Id $Id -Name $Name

# add route
$routePath = "/pode.web-dynamic/elements/steps/$($Id)"
$routePath = "/pode.web-dynamic/elements/steps/$($Id)/submit"
if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) {
# check for scoped vars
$ScriptBlock, $usingVars = Convert-PodeScopedVariables -ScriptBlock $ScriptBlock -PSSession $PSCmdlet.SessionState
Expand Down Expand Up @@ -4087,7 +4087,7 @@ function New-PodeWebStep {
$Id = Get-PodeWebElementId -Tag Step -Name $Name

# add route
$routePath = "/pode.web-dynamic/elements/step/$($Id)"
$routePath = "/pode.web-dynamic/elements/step/$($Id)/submit"
if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) {
# check for scoped vars
$ScriptBlock, $usingVars = Convert-PodeScopedVariables -ScriptBlock $ScriptBlock -PSSession $PSCmdlet.SessionState
Expand Down
2 changes: 1 addition & 1 deletion src/Public/Navigation.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function New-PodeWebNavLink {
UsingVariables = $usingVars
}

$routePath = "/pode.web-dynamic/elements/nav-link/$($Id)"
$routePath = "/pode.web-dynamic/elements/nav-link/$($Id)/click"
if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) {
$auth = $null
if (!$NoAuthentication) {
Expand Down
78 changes: 41 additions & 37 deletions src/Templates/Public/scripts/templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -2168,35 +2168,37 @@ class PodeButton extends PodeFormElement {
bind(data, sender, opts) {
super.bind(data, sender, opts);

// bind click
this.listen(this.element, 'click', function(e, target, sender) {
// hide tooltip
sender.tooltip(false);
var inputs = {};

// find group
var group = sender.element.closest('.pode-element-group');
if (group && group.length > 0) {
inputs = sender.serialize(group);
}
// bind click if dynamic
if (this.dynamic) {
this.listen(this.element, 'click', function(e, target, sender) {
// hide tooltip
sender.tooltip(false);
var inputs = {};

// find a form, if no group found
if (!group || group.length == 0) {
var form = sender.element.closest('form');
if (form && form.length > 0) {
inputs = sender.serialize(form);
// find group
var group = sender.element.closest('.pode-element-group');
if (group && group.length > 0) {
inputs = sender.serialize(group);
}
}

// get a data value
var dataValue = getDataValue(sender.element);
if (dataValue) {
inputs.data = addFormDataValue(inputs.data, 'Value', dataValue);
}
// find a form, if no group found
if (!group || group.length == 0) {
var form = sender.element.closest('form');
if (form && form.length > 0) {
inputs = sender.serialize(form);
}
}

// invoke url
sendAjaxReq(sender.url, inputs.data, sender, true, null, null, inputs.opts, $(e.currentTarget));
});
// get a data value
var dataValue = getDataValue(sender.element);
if (dataValue) {
inputs.data = addFormDataValue(inputs.data, 'Value', dataValue);
}

// invoke url
sendAjaxReq(`${sender.url}/click`, inputs.data, sender, true, null, null, inputs.opts, $(e.currentTarget));
});
}
}

spinner(show) {
Expand Down Expand Up @@ -2822,7 +2824,7 @@ class PodeTable extends PodeRefreshableElement {

// things get funky here if we have a table with a 'for' attr
// if so, we need to serialize the form, and then send the request to the form instead
var url = this.url;
var url = `${this.url}/data`;

if (this.element.attr('for')) {
var form = $(`#${this.element.attr('for')}`);
Expand Down Expand Up @@ -3903,7 +3905,7 @@ class PodeTimer extends PodeContentElement {
}

invoke(data, sender, opts) {
sendAjaxReq(this.url, null, null, true);
sendAjaxReq(`${this.url}/trigger`, null, null, true);
}
}
PodeElementFactory.setClass(PodeTimer);
Expand Down Expand Up @@ -4045,7 +4047,7 @@ class PodeTile extends PodeRefreshableElement {

// call url for dynamic tiles
if (this.dynamic) {
sendAjaxReq(this.url, null, this, true);
sendAjaxReq(`${this.url}/data`, null, this, true);
}

// if not dynamic, and fully created, click refresh buttons of sub-elements
Expand Down Expand Up @@ -4505,7 +4507,7 @@ class PodeChart extends PodeRefreshableElement {

// things get funky here if we have a chart with a 'for' attr
// if so, we need to serialize the form, and then send the request to the form instead
var url = this.url;
var url = `${this.url}/data`;

if (this.element.attr('for')) {
var form = $(`#${this.element.attr('for')}`);
Expand Down Expand Up @@ -4786,11 +4788,14 @@ class PodeModal extends PodeContentElement {
return;
}

e.preventDefault();
e.stopPropagation();

var btn = obj.element.find('div.modal-footer button.pode-modal-submit')
if (btn) {
btn.trigger('click');
}
});
}, true);

this.listen(this.element.find("div.modal-footer button.pode-modal-submit"), 'click', function(e, target) {
// get url
Expand All @@ -4801,11 +4806,10 @@ class PodeModal extends PodeContentElement {

// find a form
var inputs = {};
// var form = null;
var method = 'post';

if (obj.asForm) {
var form = obj.getElement(); // .element.find('div.modal-body form');
var form = obj.getElement();

var action = form.attr('action');
if (action) {
Expand Down Expand Up @@ -5005,7 +5009,7 @@ class PodeSelect extends PodeFormElement {
load(data, sender, opts) {
super.load(data, sender, opts);
if (this.dynamic) {
sendAjaxReq(this.url, null, this, true);
sendAjaxReq(`${this.url}/options`, null, this, true);
}
}

Expand Down Expand Up @@ -5719,7 +5723,7 @@ class PodeSteps extends PodeContentElement {

submit() {
var result = this.serialize();
sendAjaxReq(this.url, result.data, this, true, null, null, result.opts);
sendAjaxReq(`${this.url}/submit`, result.data, this, true, null, null, result.opts);
}

addChild(element, data, sender, opts) {
Expand Down Expand Up @@ -5817,7 +5821,7 @@ class PodeStep extends PodeContentElement {

if (obj.dynamic) {
var result = obj.serialize();
sendAjaxReq(obj.url, result.data, obj, true, (_, sender) => {
sendAjaxReq(`${obj.url}/submit`, result.data, obj, true, (_, sender) => {
if (!hasValidationErrors(sender)) {
obj.parent.next();
}
Expand All @@ -5836,7 +5840,7 @@ class PodeStep extends PodeContentElement {

if (obj.dynamic) {
var result = obj.serialize();
sendAjaxReq(obj.url, result.data, obj, true, (_, sender) => {
sendAjaxReq(`${obj.url}/submit`, result.data, obj, true, (_, sender) => {
if (!hasValidationErrors(sender)) {
obj.parent.submit();
}
Expand Down Expand Up @@ -5993,7 +5997,7 @@ class PodeNavLink extends PodeNavElement {

if (this.dynamic) {
this.listen(this.element, 'click', function(e, target) {
sendAjaxReq(obj.url, null, null, true);
sendAjaxReq(`${obj.url}/click`, null, null, true);
});
}
}
Expand Down

0 comments on commit 2628e90

Please sign in to comment.