Selected option doesn't render correctly in modal

What seems to be the problem: When I want to edit a product, it opens a modal where the data of that product is loaded, but where I have a select where it should show by default the category that that product had, it always shows the first entry of the options that the select has.
The strange thing is that when I inspect the code I can see that it has the property “selected” in the category that corresponds to it, however in the modal it always shows the first option.

Code:

livewire view: show-products.blade.php

show-products.blade.php

`


@foreach ($products as $product)


{{$product->idProduct}}


{{$product->prdName}}


@livewire(‘edit-product’, [‘product’ => $product], key($product->idProduct))


@endforeach `

livewire view: edit-product.blade.php

edit-product.blade.php

`




<x-jet-dialog-modal wire:model="open">
     <x-slot name="title">
         Edit product
     </x-slot>

     <x-slot name="content">
         ...
         <div>
             <select name="idCategory" class="form-control" wire:model="idCategory">
                 @foreach ($categories as $category)
                     <option @if ($product->idCategory == $category->idCategory) selected @endif
                             value="{{ $category->idCategory }}" >
                             {{ $category->name }}
                     </option>
                 @endforeach
             </select>
         </div>
         ...
     </x-slot>

     <x-slot name="footer">
         <x-jet-secondary-button wire:click="$set('open', false)">
             Cancel
         </x-jet-secondary-button>
         <x-jet-danger-button wire:click="save" wire:loading.attr="disabled" class="disabled:opacity-25">
            Update
         </x-jet-danger-button>
     </x-slot>

</x-jet-dialog-modal>

`

Livewire component: EditProduct.php

EditProduct.php

`
<?php
namespace App\Http\Livewire;

use App\Models\Category;
use App\Models\Product;
use Livewire\Component;
class EditProduct extends Component

{
    public $open = false;
    public $product, $prdName, $idCategory;
    protected $rules = [
            'product.prdName' =>'required|min:2|max:30',
            'product.idCategories' =>'required|numeric',
        ];

    public function mount(Product $product)
    {
        $this->product = $product;
    }

    public function save()
    {
        $this->validate();
        $this->product->save();
        $this->reset();

        $this->emitTo('show-products','render');
        $this->emit('alert', 'Product updated');
    }

    public function render()
    {
        $categories = Category::all();
        return view('livewire.edit-product', compact('categories'));
    }
}

`

image

Could you share the partial blade code and the code when you load the property to be bind?

Hi Prospero, yes. I think it would be easier for you to see it from my repository: LINK

I traslated the variables and others in this topic to english because this is a english forum but it’s originally in spanish.

BTW, I just “committed” an option to get the category of the product selected, you will see it commented, but I don’t think this is the way, I don’t really know how to fix it.

@satoshi but using the same dot notation don’t work??? I mean in wire:model=“producto.idCategoria”?
When I do this, don’t care more about the wrapped data because livewire data binding take care of it. I write this kind of logic different on edit function, because as you can see when you click “Save” button always it’s going to validate all data, save the same data if there’s no changes mades and emit the flash message ‘El producto se actualizo satisfactoriamente’ without any changes made in form’s fields. Maybe it’s more code writing but maybe it’s more responsible at storing data, taking care of it or doing lower the interchange with database. This is my solution
in component

public $producto, $nombre, $marca, $categoria, $prevNombre, $prevMarca, $prevCategoria;

public function mount(Producto $producto)
{
    $this->producto = $producto;

    $this->nombre = $this->producto->nombre;
    $this->marca= $this->producto->marca;
    $this->categoria = $this->producto->categoria;

    $this->prevNombre = $this->producto->nombre;
    $this->prevMarca = $this->producto->nombre;
    $this->prevCategoria = $this->producto->nombre;  
}

public function render()
{
    $marcas = Marca::all();
    $categorias = Categoria::all();
    return view('livewire.edit-producto', compact('marcas','categorias'));
}

public function save()
{
   $data = [];
   $validateData = [];
   if($this->nombre != $this->prevNombre) {
        $data = array_merge($data, ['nombre' => $this->nombre]);
        $validateData = array_merge($validateData, ['nombre' => 'required|min:2|max:30']);
   }
   //....check for other diffs
   $validator = Validator::make($data, $validateData)->validate();
   if(count($validator)) {                     //....only update and emit if change some data
      $this->producto->update($validator);
      $this->emit('message', 'Actualizado');
   }
  $this->closeModal();
  $this->cleanVars(); 
}

and in blade

<input type="text" wire:model="nombre">
<select wire:model="marca">
   @foreach($marcas as $item)
       <option value="{{ $item->id }}">{{ $item->some }}</option>
   @endforeach
</select>
<select wire:model="categoria">
   @foreach($categorias as $item)
       <option value="{{ $item->id }}">{{ $item->another }}</option>
   @endforeach
</select>

yeahhh…it’s crazy, I have a lot of write wishes hahaha
PD: si hermano, aqui tenemos que escribir en Ingles pero se puede recibir mucha ayuda! Saludos

1 Like

:man_facepalming:
I forgot the **producto.**idCategoria
That fixed the issue.
About the update/save actually I didn’t work on that, but was in my plans to do exactly what you have done, thanks for showing your way it will help me!

:rofl: no me esperaba eso jajaj, gracias buen hombre!

1 Like