Kazuto's avatar

Livewire reloads complete page after action

Hey guys,

Maybe one of you can help.

When I submit an action the code is executed but the page completely reloads after it.

I'm using Laravel 10.25.1 with Livewire 3.0.10. As a development server I'm using Herd.

Here's a gif that demonstrates the issue more clearly.

This is my component

<div wire:init="loadConfig">
    <div class="flex gap-4 mb-4">
        <div>
            <input id="connection_mysql" name="connection" type="radio" wire:model.live="connection"
                   value="mysql" @checked($connection === 'mysql')>
            <label for="connection_mysql">MySQL</label>
        </div>
        <div>
            <input id="connection_pgsql" name="connection" type="radio" wire:model.live="connection"
                   value="pgsql" @checked($connection === 'pgsql')>
            <label for="connection_pgsql">PostgreSQL</label>
        </div>
        <div>
            <input id="connection_sqlite" name="connection" type="radio" wire:model.live="connection"
                   value="sqlite" @checked($connection === 'sqlite')>
            <label for="connection_sqlite">SQLite</label>
        </div>
    </div>

    @if($tested && $invalid)
        <x-alert type="error">
            Connection failed
        </x-alert>
    @endif
    @if($tested && !$invalid)
        <x-alert type="success" class="mt-2">
            Connection successful
        </x-alert>
    @endif

    <div>
        <x-text-input label="Database Name" id="database" name="database" wire:model="database" :value="$database"/>

        @if($connection !== 'sqlite')
            <div class="grid grid-cols-[1fr_0.4fr] gap-4 w-full">
                <x-text-input label="Host" id="host" name="host" wire:model="host" :value="$host"/>
                <x-text-input label="Port" id="port" name="port" wire:model="port" :value="$port"/>
            </div>
            <div class="grid grid-cols-2 gap-4">
                <x-text-input label="Username" id="username" name="username" wire:model="username" :value="$username"/>
                <x-text-input label="Password" id="password" name="password" type="password" wire:model="password"
                              :value="$password"/>
            </div>
        @endif

        <div class="flex justify-between">
            <x-button :disabled="$invalid">Next</x-button>
            <x-button wire:click.prevent="testConnection" default>Test</x-button>
        </div>
    </div>
</div>
<?php

namespace App\Livewire;

use Artisan;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Arr;
use Illuminate\Support\Env;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Illuminate\Support\Stringable;
use Livewire\Component;
use Throwable;

class DatabaseConnection extends Component
{
    public ?string $connection = null;

    public ?string $database = null;

    public ?string $host = null;

    public ?int $port = null;

    public ?string $username = null;

    public ?string $password = null;

    public ?bool $invalid = true;

    public bool $tested = false;

    public function render(): View
    {
        return view('livewire.database-connection');
    }
    
    public function loadConfig(): void
    {
        Artisan::call('config:clear');

        $this->connection = config('database.default');

        $config = config('database.connections.'.$this->connection);

        $database = $this->connection === 'sqlite'
            ? basename(Arr::get($config, 'database'))
            : Arr::get($config, 'database');

        $this->fill([
            'database' => $database,
            'host' => Arr::get($config, 'host'),
            'port' => Arr::get($config, 'port'),
            'username' => Arr::get($config, 'username'),
            'password' => Arr::get($config, 'password'),
        ]);
    }
    
    public function testConnection()
    {
        $this->setConfig();

        Artisan::call('config:cache');

        $this->tested = true;

        try {
            DB::connection()->getPdo();
        } catch (Throwable) {
            $this->invalid = true;

            return;
        }

        $this->invalid = false;
    }

    private function setConfig(): void
    {
        $this->setEnv('DB_CONNECTION', $this->connection);
        $this->setEnv('DB_DATABASE', $this->parseDatabaseName());
        $this->setEnv('DB_HOST', $this->host);
        $this->setEnv('DB_PORT', $this->port);
        $this->setEnv('DB_USERNAME', $this->username);
        $this->setEnv('DB_PASSWORD', $this->password);
    }

    private function setEnv(string $key, string $value): void
    {
        $path = app_path('../.env');
        $replacement = "{$key}={$value}";

        try {
            Env::getOrFail($key);
        } catch (Throwable) {
            File::append($path, "$replacement\n");

            return;
        }

        $needle = Str::of($key)
            ->append('=')
            ->when(Env::get($key), fn (Stringable $string) => $string->append(Env::get($key)))
            ->toString();

        File::replaceInFile($needle, $replacement, app_path('../.env'));
    }

    private function parseDatabaseName(): string
    {
        if ($this->connection !== 'sqlite') {
            return $this->database;
        }

        return Str::of($this->database)
            ->when(! Str::endsWith($this->database, '.sqlite'),
                function (Stringable $string) {
                    return $string->append('.sqlite');
                })
            ->toString();
    }
}

I have absolutely no clue why the whole page should reload and it's not anything I've ever experienced with livewire before.

0 likes
0 replies

Please or to participate in this conversation.