简体   繁体   中英

Laravel livewire trouble when using mutators and accessor

I try to input a model the properties of which are float numbers that are stored in database in a definite unit eg for volume : liters. I want the user being able to see and enter the values in a unit of their choice eg US Gallons instead of liters letting the possibility of choosing an other unit at any time eg US Pint or hectoliter. To achieve this I allow every user to store a unit set for various pysical quantities.

What I intend to do is to create mutators and accessors based on the untis the user has chosen to transform custom units to liters before saving and to transform liters to custom units at getting. Here is an excerpt of my model

    class Equipment extends Model
{
    use HasFactory;
    protected $table = "equipments";
    protected $fillable = [
        'name',
        ...
        'boiler_volume',
        'boiler_dead_volume',
        ...
    ];

    protected $appends = ['boiler_volume','boiler_dead_volume'];

    //get the user's unit transformation factor (it works and return a float number)
    private function getKVolume()
    {
        $units = Unitset::where('user_id', auth()->user()->id)->first();
        return explode(',', $units->volume)[2];
    }

    //BOILER-----------------
    public function setBoilerVolumeAttribute($value)
    {
        if (is_numeric($value) and $value !== null and $value != 0) {
            $this->attributes['boiler_volume'] = $value * $this->getKVolume();
        }
    }
    public function getBoilerVolumeAttribute($value)
    {
        if (is_numeric($value)) {
            return $value / $this->getKVolume();
        }
    }
    //------------------
    public function setBoilerDeadVolumeAttribute($value)
    {
        if (is_numeric($value) and $value !== null and $value != 0) {
            $this->attributes['boiler_dead_volume'] = $value * $this->getKVolume();
        }
    }

    public function getBoilerDeadVolumeAttribute($value)
    {
        if (is_numeric($value)) {
            return $value / $this->getKVolume();
        }
    }

Now comes the rules in the livewire component

protected $rules =[
    ...
    'equipment.boiler_volume'=>'required|numeric',
    'equipment.boiler_dead_volume'=>'required|numeric',
    ...
];

and finally the relevant part of the form in the blade view

<x-input.group label="{{ __('Boiler Tun Volume ') }} ({{ explode(',', $unitset->volume)[0] }})" for='
            boiler_volume' :error="$errors->first('equipment.boiler_volume')"
        class="flex flex-col w-full p-2 border border-jbrown-peachpuf bg-jbrown-darker rounded-md ">
        <x-input.text wire:model.lazy="equipment.boiler_volume" type="number" step="0.001"
            class="border border-red-200 bg-red-100" name="boiler_volume" id="boiler_volume" value="" />
    </x-input.group>
    <x-input.group label="{{ __('Boiler Tun Dead Volume ') }} ({{ explode(',', $unitset->volume)[0] }})" for='
            boiler_dead_volume' :error="$errors->first('equipment.boilen_dead_volume')"
        class="flex flex-col w-full p-2 border border-jbrown-peachpuf bg-jbrown-darker rounded-md ">
        <x-input.text wire:model="equipment.boiler_dead_volume" type="text" class="border border-red-200 bg-red-100"
            name="boiler_dead_volume" id="boiler_dead_volume" value="" />
    </x-input.group>

As you can see the first input use a number type while the second on use a text type. This is only for explanation as the trouble is the same either with number input type or text input type. But now let me say what the trouble is.

What is the trouble? The trouble is that for the second field equipment.boiler_dead_volume as soon as you have input a value you cannot delete it (for example for correction). You can delete all the digits you have entered but the first one. Nevertheless, if you use the left arrow key to place the cursor at the beginning of the field, you can enter a new value, then delete the last char but never let the field empty. It's rather annoying for the user.

I must add that this behavior doesn't exist if mutators and accessors are not used. In addition, the first field for boiler_volume works normally even with accessor and mutator. Last and final, all other fields behaves the same ie wrongly.

Note The line

 protected $appends=...

doesn't change anything.

Other strange behavior Looking at the mutators and accessors you can see some checking that the value is numeric and not null. This is due to the fact that without this checks, everytime a field is emptied, the application complains that the value is not numeric.

I would be happy to get some help troubleshooting this!

It seems that wire:model.lazy is mandatory. In the first group I used it at another time without being aware of it. So, lazyness is mandatory in this case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM