2

I have a problem with my code the select2 is displaying only once when I refresh the page but it disappears when I submit the form or if there was a validation error it will disappear too. I tried wire:ignore The select2 doesn't disappear but it stops working properly and the form considered it like if it doesn't exist. I use laravel 8, livewire 2 and turbolinks. Any help would be appreciated I've been stuck for almost 2 weeks. Here is my code :

Blade:

 <form wire:submit.prevent="submit">
            {{ csrf_field() }}
            <div class="form-group row">
                <label for="to" class="col-form-label col-md-1">à :</label>
                <div class="col-md-11" >
                    <select  class="form-control mul-select" wire:model.lazy="id_to" name="id_to[]" multiple="multiple">
                        <option value="test@gmail.com">test@gmail.com</option>
                        <option value="test5@gmail.com">test5@gmail.com</option>
                    </select>
                    <div class="text-danger">
                        @error('id_to')
                            <span>
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>
                </div>
            </div>
            <div class="form-group row">
                <label for="cc" class="col-form-label col-md-1">Cc :</label>
                <div class="col-md-11">
                    <input type="text" class="form-control" wire:model.lazy="cc" name="cc" placeholder="Cc">
                    <div class="text-danger">
                        @error('cc')
                            <span>
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>
                </div>
            </div>
            <div class="form-group row">
                <label for="sujet" class="col-form-label col-md-1">Sujet :</label>
                <div class="col-md-11">
                    <input type="text" class="form-control" wire:model.lazy="sujet" name="sujet" placeholder="Sujet">
                    <div class="text-danger">
                        @error('sujet')
                            <span>
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>
                </div>
            </div>
            <div class="form-group row">
                <label for="message" class="col-form-label col-md-1">Message :</label>
                <div class="col-md-11">
                    <textarea class="form-control" name="message" wire:model.lazy="message" rows="8"></textarea>
                    <div class="text-danger">
                        @error('message')
                            <span>
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>
                </div>
            </div>
           {{-- <div class="email-editor">
                <textarea class="form-control" id="summary-ckeditor" name="summary-ckeditor" wire:model.lazy="message"></textarea>
                <div class="text-danger">
                    @error('message')
                        <span>
                            <strong>{{ $message }}</strong>
                        </span>
                    @enderror
                </div>
             </div> --}}
                <div class="email-action mt-3">
                    <button class="btn btn-primary" type="submit">Envoyer</button>
                    <button class="btn btn-warning" wire:click="resetForm">Reset</button>
                </div>
        </form>



<script type="text/javascript">

        document.addEventListener("livewire:load", function (event) {
           $(document).ready(function() {
               $('.mul-select').select2();
           });
          });
  
</script>

Component:

  public $id_to, $id_from, $sujet, $cc, $message;

public $rules=[

    'id_to' => 'required',
    'id_from' => '',
    'cc' => '',
    'sujet' => 'required|max:30',
    'message' => 'required|max:155',

];
    public function render()
{
    return view('livewire.admin.messages.messages');
}

public function submit()
{
    $validateData=$this->validate();
    $to_email=User::where('email', $validateData['id_to'])->first();


             Mail::send(array(), array(), function ($message) {
            $validateData=$this->validate();
            $emails=$validateData['id_to'];

            foreach($emails as $email)
            {
            $message->to($email)
              ->subject($validateData['sujet'])
              ->from(Auth::user()->email, 'ADMIN')
              ->setBody($validateData['message']);
            }
          });

    $validateData['id_from']=Auth::user()->id;
    $validateData['id_to']= implode(",", $to_email->id);
    SendMessage::create($validateData);

    session()->flash('success', 'data has been sent successfully');
    $this->resetForm();
}
public function resetForm()
{
    $this->id_to = '';
    $this->cc = '';
    $this->sujet = '';
    $this->message = '';
}
Nano
  • 87
  • 1
  • 10

2 Answers2

4

Here is a simple way to achieve that

<div class="col-md-11">
    <div wire:ignore> // this will make sure to ignore DOM changes
        <select
            class="form-control"
            id="mul-select"
            name="id_to[]"
            multiple="multiple"
         >
             <option value="test@gmail.com">test@gmail.com</option>
             <option value="test5@gmail.com">test5@gmail.com</option>
        </select>
    </div>
    <div class="text-danger">
        @error('id_to')
            <span>
                <strong>{{ $message }}</strong>
            </span>
        @enderror
    </div>
</div>

And then outside of your component root tag make sure you push this script to your layout

@push('scripts')
<script>
    $(document).ready(function () {
        $('#mul-select').select2();

         $(document).on('change', '#mul-select', function (e) {
             //when ever the value of changes this will update your PHP variable 
            @this.set('id_to', e.target.value);
        });
    });
</script>
@endpush

Finally, on your layout file append the pushed script like this just before closing your body tag

    @stack('scripts')
</body
kenean50
  • 518
  • 5
  • 13
  • Thank you so much it works but there is a problem I Have this variable in component $emails=$validateData['id_to']; which needs to have an array of emails but it's not working, it only consider the last email I clicked on :( – Nano Jun 12 '21 at 09:34
  • maybe make changes on the @this.set() method like this and try it `@this.set('id_to', e.target.value);` to `@this.set('id_to', $('#mul-select').val());` – kenean50 Jun 13 '21 at 20:24
  • if your component variable name is `$validateData` it should be more like this `@this.set('validateData.id_to', $('#mul-select').val());` – kenean50 Jun 13 '21 at 20:30
0

Normally for select2 in Livewire I use hydration for element's rerender.

<div class="form-group row" wire:ignore.self>  // I'm not sure about this it's necessary
  <label for="to" class="col-form-label col-md-1">à :</label>
  <div class="col-md-11" >
     <select  class="form-control mul-select" wire:model.lazy="id_to" name="id_to[]" multiple="multiple">
        <option value="test@gmail.com">test@gmail.com</option>
        <option value="test5@gmail.com">test5@gmail.com</option>
     </select>
     <div class="text-danger">
        @error('id_to') <span><strong>{{ $message }}</strong></span>  @enderror
     </div>
  </div>
</div>

//......
<script>
         
   $(document).ready(function() {
            window.initSelectDrop=()=>{
                $('.mul-select').select2({
                    placeholder: '{{ __('locale.Select') }}',
                    allowClear: true});
            }
            initSelectDrop();
            $('.mul-select').on('change', function (e) {
                livewire.emit('selectedCompanyItem', e.target.value)
            });
            window.livewire.on('select2',()=>{
                initSelectDrop();
            });
   });
  
</script>

in component

public function hydrate()
{
   $this->emit('select2');
}

protected $listeners = [
   'selectedCompanyItem'
];

public function selectedCompanyItem($value)
{
   dd($value);
}
Prospero
  • 2,190
  • 2
  • 4
  • 18