Opening modal from a custom page

Is it possible to open a modal from a class that extends Page? $this->dispatch doesn't seem to be working, I want the modal to automatically open at the end of my submit function
Solution:
Laravel
Properties | Laravel
A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
Jump to solution
21 Replies
Jamie Cee
Jamie Cee2mo ago
Bump
LeandroFerreira
LeandroFerreira2mo ago
possible, but we need to check some code that you are trying
Jamie Cee
Jamie Cee2mo ago
public function submit()
{
/* get the form data */
$data = $this->form->getState();

/* Define an array for the methods to be disabled */
$disabled = [];

/* Loop the method toggles from the form data */
foreach ($data as $item => $val) {

/* If a value is set to false, add to the disabled array */
if (!$val) {
$disabled[] = $item;
}

/* Check if method is enabled within the config and if the method is already enabled against the user */
if (
$val
&& $this->isMethodEnabled($item)
&& !$this->isMethodAlreadyEnabled($item)
) {
/* Enable the method */
$this->enableMethod($item);
}
}

/* If no methods are selected */
if (
count($disabled) == count($this->countEnabledMethods())
&& $this->isUserOrganisationTwofaRequired()
) {
\Filament\Notifications\Notification::make()
->title('One of your organisations requires you to use two-factor authentication')
->icon('heroicon-o-exclamation-triangle')
->iconColor(Color::hex('#D63230'))
->send();

return redirect()->back();
}

/* Loop the disabled array and disable the methods */
$this->loopDisableMethods($disabled);

/* TODO: Open modal for scanning a qr code here instead of needing an action button */

/* Everything updated here */
\Filament\Notifications\Notification::make()
->title('We have successfully updated your two-factor authentication methods')
->icon('heroicon-o-check-badge')
->iconColor(Color::hex('#38c172'))
->send();

/* Return back */
$this->dispatch('reload');
return redirect()->back();
}
public function submit()
{
/* get the form data */
$data = $this->form->getState();

/* Define an array for the methods to be disabled */
$disabled = [];

/* Loop the method toggles from the form data */
foreach ($data as $item => $val) {

/* If a value is set to false, add to the disabled array */
if (!$val) {
$disabled[] = $item;
}

/* Check if method is enabled within the config and if the method is already enabled against the user */
if (
$val
&& $this->isMethodEnabled($item)
&& !$this->isMethodAlreadyEnabled($item)
) {
/* Enable the method */
$this->enableMethod($item);
}
}

/* If no methods are selected */
if (
count($disabled) == count($this->countEnabledMethods())
&& $this->isUserOrganisationTwofaRequired()
) {
\Filament\Notifications\Notification::make()
->title('One of your organisations requires you to use two-factor authentication')
->icon('heroicon-o-exclamation-triangle')
->iconColor(Color::hex('#D63230'))
->send();

return redirect()->back();
}

/* Loop the disabled array and disable the methods */
$this->loopDisableMethods($disabled);

/* TODO: Open modal for scanning a qr code here instead of needing an action button */

/* Everything updated here */
\Filament\Notifications\Notification::make()
->title('We have successfully updated your two-factor authentication methods')
->icon('heroicon-o-check-badge')
->iconColor(Color::hex('#38c172'))
->send();

/* Return back */
$this->dispatch('reload');
return redirect()->back();
}
So where I dispatch('reload') I want to add a way to open my modal straight away, and this is my blade
<x-filament-panels::page>
@if (!session()->get('validated_multifactor_auth'))
<x-filament::button wire:click="chooseMethod" color="warning">
Verify two-factor authentication
</x-filament::button>
@endif

@if ($this->userAuthenticatorEnabled())
<x-filament::modal id="view-qr-code">
<x-slot name="trigger">
<x-filament::button color="recite_blue">
View Authenticator QR Code
</x-filament::button>

</x-slot>

{{-- Modal content --}}
<x-slot name="heading">
<h2 class="text-lg font-semibold">Scan the QR code</h2>
<p>Scan this code into your authenticator app</p>
</x-slot>

@if ($this->displayVerifyCode)
<x-slot name="footer">
<p>Verify authenticator</p>
<x-filament-panels::form wire:submit="verify">
{{ $this->verifyForm }}
<div>
<x-filament::button type="submit" size="sm" wire:loading.attr="disabled" wire:target="verify"
wire:loading.class="opacity-50 cursor-not-allowed">
Verify
</x-filament::button>
</div>
</x-filament-panels::form>
</x-slot>
@endif

{{-- <p>Scan the QR code below with your authenticator app</p> --}}
<img src="{{ $this->getAuthenticatorQRCode() }}" alt="QR Code">
</x-filament::modal>
@endif


<x-filament-panels::form wire:submit="submit">
{{ $this->form }}
<div>
<x-filament::button type="submit" size="sm" wire:loading.attr="disabled" wire:target="submit"
wire:loading.class="opacity-50 cursor-not-allowed">
Submit
</x-filament::button>
</div>
</x-filament-panels::form>

</x-filament-panels::page>
<x-filament-panels::page>
@if (!session()->get('validated_multifactor_auth'))
<x-filament::button wire:click="chooseMethod" color="warning">
Verify two-factor authentication
</x-filament::button>
@endif

@if ($this->userAuthenticatorEnabled())
<x-filament::modal id="view-qr-code">
<x-slot name="trigger">
<x-filament::button color="recite_blue">
View Authenticator QR Code
</x-filament::button>

</x-slot>

{{-- Modal content --}}
<x-slot name="heading">
<h2 class="text-lg font-semibold">Scan the QR code</h2>
<p>Scan this code into your authenticator app</p>
</x-slot>

@if ($this->displayVerifyCode)
<x-slot name="footer">
<p>Verify authenticator</p>
<x-filament-panels::form wire:submit="verify">
{{ $this->verifyForm }}
<div>
<x-filament::button type="submit" size="sm" wire:loading.attr="disabled" wire:target="verify"
wire:loading.class="opacity-50 cursor-not-allowed">
Verify
</x-filament::button>
</div>
</x-filament-panels::form>
</x-slot>
@endif

{{-- <p>Scan the QR code below with your authenticator app</p> --}}
<img src="{{ $this->getAuthenticatorQRCode() }}" alt="QR Code">
</x-filament::modal>
@endif


<x-filament-panels::form wire:submit="submit">
{{ $this->form }}
<div>
<x-filament::button type="submit" size="sm" wire:loading.attr="disabled" wire:target="submit"
wire:loading.class="opacity-50 cursor-not-allowed">
Submit
</x-filament::button>
</div>
</x-filament-panels::form>

</x-filament-panels::page>
Removed some h and p tags to hit character limit
LeandroFerreira
LeandroFerreira2mo ago
what is reload ?
Jamie Cee
Jamie Cee2mo ago
I defined that to just reload the page as the redirect back wasn't live refreshing, so when I have conditional buttons, they wouldn't display without the reload I tried the modal opening without that reload there to no avail
LeandroFerreira
LeandroFerreira2mo ago
would you like to open this modal? <x-filament::modal id="view-qr-code"> $this->dispatch('open-modal', id: 'view-qr-code') ?
Jamie Cee
Jamie Cee2mo ago
Yeah I tried that but it wasn't opening.
LeandroFerreira
LeandroFerreira2mo ago
Could you try only this, just to see if it is working?
<x-filament-panels::page>
<div>
<x-filament::modal id="view-qr-code">
<x-slot name="trigger">
<x-filament::button color="primary">
View Authenticator QR Code
</x-filament::button>
</x-slot>

{{-- Modal content --}}
<x-slot name="heading">
<h2 class="text-lg font-semibold">Scan the QR code</h2>
<p>Scan this code into your authenticator app</p>
</x-slot>
</x-filament::modal>

<x-filament-panels::form wire:submit="submit">
{{ $this->form }}
<div>
<x-filament::button type="submit" size="sm" wire:loading.attr="disabled" wire:target="submit">
Submit
</x-filament::button>
</div>
</x-filament-panels::form>

</div>
</x-filament-panels::page>
<x-filament-panels::page>
<div>
<x-filament::modal id="view-qr-code">
<x-slot name="trigger">
<x-filament::button color="primary">
View Authenticator QR Code
</x-filament::button>
</x-slot>

{{-- Modal content --}}
<x-slot name="heading">
<h2 class="text-lg font-semibold">Scan the QR code</h2>
<p>Scan this code into your authenticator app</p>
</x-slot>
</x-filament::modal>

<x-filament-panels::form wire:submit="submit">
{{ $this->form }}
<div>
<x-filament::button type="submit" size="sm" wire:loading.attr="disabled" wire:target="submit">
Submit
</x-filament::button>
</div>
</x-filament-panels::form>

</div>
</x-filament-panels::page>
public function submit(): void
{
$data = $this->form->getState();
$this->dispatch('open-modal', id: 'view-qr-code');
}
public function submit(): void
{
$data = $this->form->getState();
$this->dispatch('open-modal', id: 'view-qr-code');
}
Jamie Cee
Jamie Cee2mo ago
Sure, gimme half an hour, just travelling to the office Yeah, that opens. If I re-add my original code, it works without the reload dispatch, but my original blade fails, so could be something to do with it having if blocks etc?
LeandroFerreira
LeandroFerreira2mo ago
try to move @if ($this->userAuthenticatorEnabled()) to the modal button View Authenticator QR Code
Jamie Cee
Jamie Cee2mo ago
Yeah updated it to this
<x-filament::modal id="view-qr-code">
@if ($this->userAuthenticatorEnabled())
<x-slot name="trigger">
<x-filament::button color="recite_blue">
View Authenticator QR Code
</x-filament::button>

</x-slot>
@endif

{{-- Modal content --}}
<x-slot name="heading">
<h2 class="text-lg font-semibold">Scan the QR code</h2>
<p>Scan this code into your authenticator app</p>
</x-slot>

@if ($this->displayVerifyCode)
<x-slot name="footer">
<p>Verify authenticator</p>
<x-filament-panels::form wire:submit="verify">
{{ $this->verifyForm }}
<div>
<x-filament::button type="submit" size="sm" wire:loading.attr="disabled" wire:target="verify"
wire:loading.class="opacity-50 cursor-not-allowed">
Verify
</x-filament::button>
</div>
</x-filament-panels::form>
</x-slot>
@endif

@if ($this->userAuthenticatorEnabled())
<p>Scan the QR code below with your authenticator app</p>
<img src="{{ $this->getAuthenticatorQRCode() }}" alt="QR Code">
@endif
</x-filament::modal>
<x-filament::modal id="view-qr-code">
@if ($this->userAuthenticatorEnabled())
<x-slot name="trigger">
<x-filament::button color="recite_blue">
View Authenticator QR Code
</x-filament::button>

</x-slot>
@endif

{{-- Modal content --}}
<x-slot name="heading">
<h2 class="text-lg font-semibold">Scan the QR code</h2>
<p>Scan this code into your authenticator app</p>
</x-slot>

@if ($this->displayVerifyCode)
<x-slot name="footer">
<p>Verify authenticator</p>
<x-filament-panels::form wire:submit="verify">
{{ $this->verifyForm }}
<div>
<x-filament::button type="submit" size="sm" wire:loading.attr="disabled" wire:target="verify"
wire:loading.class="opacity-50 cursor-not-allowed">
Verify
</x-filament::button>
</div>
</x-filament-panels::form>
</x-slot>
@endif

@if ($this->userAuthenticatorEnabled())
<p>Scan the QR code below with your authenticator app</p>
<img src="{{ $this->getAuthenticatorQRCode() }}" alt="QR Code">
@endif
</x-filament::modal>
But I think parts still wont work because its waiting for a page refresh to make note of the changes? When I press submit, the button and qr code wont show until I refresh the page
LeandroFerreira
LeandroFerreira2mo ago
page refresh? Shouldn't it be a livewire request?
Jamie Cee
Jamie Cee2mo ago
Maybe im missing something then? My class is defined like this, if this is any use:
class EnableTwoFactorMethod extends Page implements HasForms
{
use InteractsWithForms;

protected static ?string $navigationIcon = 'heroicon-o-document-text';

protected static string $view = 'filament.pages.enable-two-factor-method';

protected static bool $shouldRegisterNavigation = false;
class EnableTwoFactorMethod extends Page implements HasForms
{
use InteractsWithForms;

protected static ?string $navigationIcon = 'heroicon-o-document-text';

protected static string $view = 'filament.pages.enable-two-factor-method';

protected static bool $shouldRegisterNavigation = false;
if I add the if also into my submit button like this, it seems to work in reverse, so toggle on, nothing, but toggle off, it displays.
if ($this->userAuthenticatorEnabled()) {
$this->dispatch('open-modal', id: 'view-qr-code');
}
if ($this->userAuthenticatorEnabled()) {
$this->dispatch('open-modal', id: 'view-qr-code');
}
So Ill have to check the logic on my function there, but the button loads after a page refresh, when the authenticator method is enabled, so I believe the check is correct?
LeandroFerreira
LeandroFerreira2mo ago
the submit button should send a livewire request, not page refresh.. as my example
Jamie Cee
Jamie Cee2mo ago
Ah nah I mean, when I physically refresh the page after the submit process has finished
LeandroFerreira
LeandroFerreira2mo ago
why are you refreshing the page?
Jamie Cee
Jamie Cee2mo ago
Because the buttons aren't displaying initially
LeandroFerreira
LeandroFerreira2mo ago
you can control this using livewire instead of refreshing the page
Jamie Cee
Jamie Cee2mo ago
I havent had much exposure to livewire fully, what would I search in the docs to get what I need?
Solution
LeandroFerreira
LeandroFerreira2mo ago
Laravel
Properties | Laravel
A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
Jamie Cee
Jamie Cee2mo ago
Cheers, Ill take a look over and try a few things, thanks for the support so far Yeah that works now, all I needed was to update my properties, so after I enable them against the user, I just had to update $this->methods. Thanks again 🙂
Want results from more Discord servers?
Add your server