fix: add polling and reset handling for single mode coordinates

Enhanced coordinate synchronization in single mode to handle Panel
actions like "Supprimer" (reset to saved values).

Issues Fixed:
- Marker not updating when clicking "Supprimer" button in Panel
- Panel "Supprimer" restores saved coordinates but marker didn't move
- No detection of programmatic field value changes

Solution:
- Add MutationObserver to detect attribute changes on input fields
- Add 500ms polling as fallback for value detection
- Add nextTick() for reactive updates to ensure proper timing
- Handle coordinate reset: when invalid, return to default center
- Proper cleanup with onBeforeUnmount for observers and intervals

Behavior:
- User changes field → marker updates immediately
- User drags marker → fields update immediately
- User clicks "Supprimer" → marker returns to saved position
- Fields cleared → marker disappears, map resets to default center

Technical Details:
- MutationObserver watches 'value' attribute on lat/lon inputs
- Polling checks every 500ms for changes missed by events
- Watcher uses nextTick() to ensure DOM updates complete
- All event listeners and observers properly cleaned up on unmount

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-01-29 14:34:28 +01:00
parent cc44a68e66
commit 818506fcfa
2 changed files with 88 additions and 40 deletions

File diff suppressed because one or more lines are too long

View file

@ -36,7 +36,7 @@
</template>
<script>
import { ref, computed, watch, onMounted, nextTick } from 'vue';
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue';
import MapPreview from '../map/MapPreview.vue';
import MarkerList from '../map/MarkerList.vue';
import { useMarkersApi } from '../../composables/useMarkersApi.js';
@ -191,6 +191,7 @@ export default {
// Watch for changes in the form fields
const form = document.querySelector('.k-form');
if (form) {
// Listen to input events
form.addEventListener('input', (e) => {
if (e.target.name && (e.target.name.includes('latitude') || e.target.name.includes('longitude'))) {
const newCoords = getCoordinatesFromForm();
@ -198,6 +199,39 @@ export default {
singleLon.value = newCoords.lon;
}
});
// Also use MutationObserver to detect value changes (e.g., from "Supprimer" button)
const latInput = form.querySelector('input[name*="latitude"]');
const lonInput = form.querySelector('input[name*="longitude"]');
if (latInput && lonInput) {
const observer = new MutationObserver(() => {
const newCoords = getCoordinatesFromForm();
if (newCoords.lat !== singleLat.value || newCoords.lon !== singleLon.value) {
singleLat.value = newCoords.lat;
singleLon.value = newCoords.lon;
}
});
// Observe attribute changes (value attribute)
observer.observe(latInput, { attributes: true, attributeFilter: ['value'] });
observer.observe(lonInput, { attributes: true, attributeFilter: ['value'] });
// Also poll periodically as a fallback
const pollInterval = setInterval(() => {
const newCoords = getCoordinatesFromForm();
if (newCoords.lat !== singleLat.value || newCoords.lon !== singleLon.value) {
singleLat.value = newCoords.lat;
singleLon.value = newCoords.lon;
}
}, 500);
// Cleanup on unmount
onBeforeUnmount(() => {
observer.disconnect();
clearInterval(pollInterval);
});
}
}
}
@ -228,9 +262,23 @@ export default {
if (props.mode === 'single') {
// Center map on new position if valid
if (!isNaN(lat) && !isNaN(lon) && lat !== null && lon !== null && lat !== 0 && lon !== 0) {
// Force immediate reactivity
nextTick(() => {
if (mapPreview.value && mapPreview.value.centerOnPosition) {
mapPreview.value.centerOnPosition(lat, lon);
}
});
} else {
// Coordinates are invalid/cleared - reset to default center
center.value = {
lat: props.defaultCenter[0],
lon: props.defaultCenter[1]
};
nextTick(() => {
if (mapPreview.value && mapPreview.value.centerOnPosition) {
mapPreview.value.centerOnPosition(center.value.lat, center.value.lon);
}
});
}
}
}