Select dependiente desde Livewire parte 2
Reny Ramos • November 30, 2020
laravel livewire livewirev2 programmingContinuando con la implementación del post anterior, ahora aplicaremos la librería select2 a los dos select del proyecto, la dificultad aquí se basa en el hecho de que esta librería modifica el DOM del select directamente, por lo tanto confunde a Livewire y este no puede llevar el control correctamente debido a que lo que espera ver no es lo que esta en realidad.
Comenzaremos con lo básico, incluir las librerías necesarias: Jquery y Select2 y ademas el CSS (personalmente me parece mucho peso agregado por esta funcionalidad en algo tan pequeño, pero lo hago por razones educativas).
Librerias que agregar css
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-beta.1/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-beta.1/dist/js/select2.min.js"></script>
Por ultimo modificamos el primer select agregando la clase necesaria y colocando el JS que activara la funcionalidad.
Comenzaremos con el primer select lvlSelect (de ahora en adelante cada select tendra su nombre y sera lvlSelect para el selector de nivel y digiSelect para el selector de Digimon) agregando un Id personalizado y la clase necesaria y colocando el JS que activara la funcionalidad, sin ningun configuracion adicional, una vez hecho esto, se comprueba que el select2 se aplique correctamente, el lvlSelect estará "funcionando" como debería, sin embargo al cambiarse el valor nada ocurre con respecto a Livewire, por lo que nos tocara encargarnos de hacer ese cambio de forma manual, comenzaremos borrando el wire:model que de momento es inútil, luego colocamos un atributo data-name para identificar el valor a actualizar, y la clase select2, para terminar con algo asi
<select id="lvlSelect" name="lvlSelect" class="custom-select select2" data-name="lvl">
Luego de eso trabajaremos sobre la acción de cambio de valor del select2, debido a que ya no es un select común toca buscar en la documentación de select2 para esta parte, trabajamos sobre el evento y disparamos una acción de actualización de valor en Livewire, quedando algo asi.
$(document).ready(function() {
$('#lvlSelect').select2();
$('.select2').on('change', function (e) {
let data = $(this).select2("val")
@this.set($(this).data('name'), data);
});
});
Con esto el primer select esta listo y funcional, bueno, no del todo, ahora esta otro detalle, debemos decirle a Livewire, no le prestes atención a este elemento, no te fijes en sus cambios, para eso tomaremos el div superior al select y agregaremos wire:ignore y adicionalmente le agregamos un name a dicho div, cuando he trabajado con Livewire 1.x agregar un name es completamente necesaria, luego a partir de la 2.0 en adelante parece que no es necesario, al menos en mi experiencia.
Ahora con esto, si estamos listo con el primer select, ahora el segundo, sera algo parecido, sin embargo esta un pequeño detalle, las opciones digiSelect cambiaran, por lo tanto cada vez que se cambie el valor del lvlSelect esto cambiara el DOM y dejara de funcionar el Select2, asi que debemos agregar codigo extra para esta parte.
Primero, debemos emitir un evento desde el componente para avisarle al front que reaplique el Select2, esto podemos hacerlo desde el método updatingLvl, quien es el que hace que el digiSelect cambie, luego desde el front simplemente escuchamos al evento y re aplicamos el select2, con eso bastaría, quedando algo así.
Search.php
public function updatingLvl($value)
{
$request = Http::get($this->baseUrl . $value);
$this->digimons = new \Illuminate\Support\Collection($request->json());
$this->avatar = $this->digimons->first()['img'];
$this->emit('reApplyS2');
}
search.blade.php
Livewire.on('reApplyS2', values => {
$('#digiSelect').select2();
})
Por ultimo dejo el link al Repositorio, mas adelante estaré agregándole mas funcionalidades a medida de que cree nuevos posts.