I have a Livewire component and inside it there is a leaflet js map. It works fine until there is a validation error or component refresh happens. When that occurs, the map disappears from the page.
This is the code in the blade file
<div>
<x-slot name="header">
{{ __('Create Campaign') }}
</x-slot>
<div class="p-4 rounded-lg shadow-xs flex items-center justify-center">
<div class="w-8/12">
<x-mary-form wire:submit="save">
<x-mary-input label="Name" wire:model="name" icon="o-user"/>
<x-mary-textarea label="Description" wire:model="description"/>
<x-mary-input label="Address" wire:model="address" icon="o-home"/>
<x-mary-datetime label="Date" wire:model="date" icon="o-calendar"/>
<x-mary-datetime label="Start Time" wire:model="startTime" icon="o-clock" type="time"/>
<x-mary-datetime label="End Time" wire:model="endTime" icon="o-clock" type="time"/>
<label>Location</label>
<div class="rounded" style="height: 400px" id="map"></div>
@error('latitude')
<x-input-error :messages="$message" />
@enderror
<x-slot:actions>
<x-mary-button link="{{ route('campaigns.index') }}" label="Cancel"/>
<x-mary-button label="Save!" class="btn-primary" type="submit" spinner="save"/>
</x-slot:actions>
</x-mary-form>
</div>
</div>
</div>
@script
<script>
const map = L.map('map', {
center: [7.29312, 80.63410],
zoom: 14,
minZoom: 12,
maxZoom: 14
});
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {}).addTo(map);
var marker = L.marker();
function onMapClick(e) {
marker.setLatLng(e.latlng).addTo(map);
console.log(e.latlng['lat']);
console.log(e.latlng['lng']);
$wire.latitude = e.latlng['lat'];
$wire.longitude = e.latlng['lng'];
}
map.on('click', onMapClick);
</script>
@endscript
@assets
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
@endassets
I'm expecting the map to be visible on the form even after the component refresh.
Livewire rewrites the DOM and this causes some conflicts with external javascript libraries as their references to the DOM are lost
To avoid this a possible solution is to add the wire:ignore attribute to the tag managed by the external library (LeafletJs in your case).
I usually prefer to enclose the tag with a <div> with the wire:ignore attribute:
<div wire:ignore>
<div class="rounded" style="height: 400px" id="map"></div>
</div>
This way Livewire will leave that <div> intact and it can be managed by the external library