Closed danielrona closed 1 week ago
@danielrona I tried your code and it worked fine for me. Can you supply your component's code as well? (re: form.phone_number
)
Maybe there's something in there that might shed some light on what you're experiencing.
@jeffchown gladly, this is stripped down and using the sushi driver
Laravel Model Company.php
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Sushi\Sushi;
final class Company extends Model
{
use Sushi;
protected $rows = [
['id' => 1,
'name' => 'Test Company',
'street' => 'Test Street',
'street_no' => '1',
'zip_code' => '12345',
'city' => 'Test City',
'country' => 'de',
'email' => '',
'phone_number' => '1234567890',
'created_at' => null,
'deleted_at' => null,
'updated_at' => null],
['id' => 2,
'name' => 'Test Company2',
'street' => 'Test Street',
'street_no' => '2',
'zip_code' => '12345',
'city' => 'Test City',
'country' => 'de',
'email' => '',
'phone_number' => '1234567890',
'created_at' => null,
'deleted_at' => null,
'updated_at' => null,
],
];
}
Livewire Component CompaniesEdit.php
<?php
declare(strict_types=1);
namespace App\Livewire\Administration;
use App\Livewire\Forms\CompanyForm;
use App\Models\Company;
use App\Traits\WithCountries;
use Livewire\Component;
final class CompaniesEdit extends Component
{
use WithCountries;
public CompanyForm $form;
public function mount(Company $company): void
{
$this->form->fill($company);
}
public function render()
{
return view('livewire.administration.companies-edit');
}
public function save(): void
{
$this->form->save();
}
}
Livewire Form CompanyForm.php
<?php
declare(strict_types=1);
namespace App\Livewire\Forms;
use App\Models\Company;
use Flux;
use Livewire\Attributes\Validate;
use Livewire\Form;
final class CompanyForm extends Form
{
#[Validate('string|nullable')]
public ?string $city = null;
#[Validate('string|nullable')]
public ?string $country = 'de';
#[Validate('email|nullable')]
public ?string $email = null;
#[Validate('integer|nullable')]
public ?int $id = null;
#[Validate('required|string|max:255')]
public ?string $name = null;
#[Validate('string|nullable')]
public ?string $old_address = null;
#[Validate('string|nullable')]
public ?string $phone_number = null;
#[Validate('string|nullable')]
public ?string $street = null;
#[Validate('string|nullable')]
public ?string $street_no = null;
#[Validate('string|nullable')]
public ?string $zip_code = null;
public function save(): Company
{
$this->validate();
$company = $this->id ? Company::find($this->id) : new Company();
$company->fill($this->toArray());
$company->save();
Flux::toast(__('Saved successfully'), variant: 'success');
return $company;
}
}
Blade File companies-form.blade.php
<div x-data="{input: false}" @keydown.ctrl.i.window.prevent="input = true">
<div class="flex justify-between items-center">
<div class="flex items-center justify-center">
<span class="relative inline-flex">
<flux:button wire:click="save" kbd="Strg+S" @keydown.ctrl.s.window.prevent="$wire.save()">
{{ __('Save') }}
</flux:button>
<span class="flex absolute h-3 w-3 top-0 right-0 -mt-1 -mr-1 hidden" wire:dirty.class.remove="hidden">
<span
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-sky-400 dark:bg-red-500 opacity-75"></span>
<span class="relative inline-flex rounded-full h-3 w-3 bg-sky-500 dark:bg-red-500"></span>
</span>
</span>
</div>
<flux:button variant="ghost" href="{{ route('companies.index') }}" wire:navigate
icon-trailing="arrow-uturn-left">
{{ __('Back') }}
</flux:button>
</div>
<flux:tab.group>
<flux:tabs>
<flux:tab name="company">{{ __('Company') }}</flux:tab>
</flux:tabs>
<flux:tab.panel name="company">
<form>
<div class="grid grid-cols-2 gap-4">
<flux:input wire:model="form.name" :label="__('Name')" :badge="__('Required')"
@focus="input = false" x-trap="input" kbd="Strg+I"/>
<flux:input icon="at-symbol" wire:model="form.email" :label="__('Email')"/>
</div>
<div class="grid grid-cols-4 gap-4">
<div class="col-span-3">
<flux:input wire:model="form.street" :label="__('Street')"/>
</div>
<flux:input wire:model="form.street_no" :label="__('Street No')"/>
</div>
<div class="grid grid-cols-4 gap-4">
<flux:input wire:model="form.zip_code" :label="__('Zip Code')"/>
<div class="col-span-3">
<flux:input wire:model="form.city" :label="__('City')"/>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<flux:select variant="listbox" :label="__('Country')" wire:model="form.country"
:placeholder="__('Please Choose')" searchable>
<flux:option class="option" :value="$form->country">
<img class="w-4 aspect-auto mr-4"
src="{{ url('/images/countries/' . $form->country . '.svg') }}"
alt="{{ $form->country }}" loading="lazy">
{{ $this->listOfCountries[$form->country] }}
</flux:option>
@foreach($this->listOfCountries as $idx => $country)
@if($idx !== $form->country)
<flux:option wire:key="{{ $idx }}">
<img class="w-4 aspect-auto mr-4"
src="{{ url('/images/countries/' . $idx . '.svg') }}" alt="{{ $idx }}"
loading="lazy">
{{ $country }}
</flux:option>
@endif
@endforeach
</flux:select>
{{-- https://github.com/livewire/flux/issues/577 --}}
{{-- <flux:input icon="phone" mask="(+99) 999 999999999999" wire:model="form.phone_number"--}}
{{-- :label="__('Phone')"/>--}}
<flux:input icon="phone" wire:model="form.phone_number" :label="__('Phone')"/>
</div>
</form>
</flux:tab.panel>
</flux:tab.group>
</div>
With the mask attribute I get
Without the blue dot is not showing till the first edit, as it's supposed to.
Thanks @danielrona - great re: Sushi. One piece missing - your WithCountries
trait
@jeffchown sorry
WithCountries.php
<?php
declare(strict_types=1);
namespace App\Traits;
trait WithCountries
{
public array $listOfCountries;
public function __construct()
{
$this->listOfCountries = ['de' => 'Germany', 'fi' => 'Test 1', 'pl' => 'Test 2'];
}
}
@danielrona I tried your code but there were still some dependencies.
Are you able to recreate the issue in a single-file Volt component to make it easier to cut & paste?
Will do, probably not before Monday though.
@danielrona try to get rid of as much code as possible in your demo too while still being able to demonstrate the issue.
Like if the issue is with the flux:input component, then only have that in your component (plus maybe something showing dirty state), and remove everything else. If possible, we would prefer a simple Volt component (or a simple Livewire class and view) that doesn't have any dependencies (no models, sushi, etc.).
If you can do that, it will make investigating the issue quicker and easier. Thanks!
Yep, closing this as it's not immediately reproducible. Also I suspect this has nothing to do with flux directly and instead alpine/livewire but I could be wrong.
When using mask on flux:input I always end up in dirty state
Anyone else having this issue?