From 64ac3ac42a9125ccf538553e97ba5b8dd0ac2c66 Mon Sep 17 00:00:00 2001 From: Adrien Foulon <6115458+Tofandel@users.noreply.github.com> Date: Tue, 26 Sep 2023 19:01:23 +0200 Subject: [PATCH] feat: add v-model to infowindow --- README.md | 42 ++++++++++++++++++++++-- docs/components/info-window.md | 60 ++++++++++++++++++++++++++++++++-- package.json | 4 ++- src/components/InfoWindow.vue | 38 ++++++++++++++++++--- 4 files changed, 134 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index c79ed57..08f48c3 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Include the following script tag in your `index.html` (make sure to include it a ``` -All the map components are available on the `Vue3GoogleMap` global variable. +All the map components are available on the `Vue3GoogleMap` global variable. [Codepen demo](https://codepen.io/husamibrahim/pen/poQXZbR) @@ -390,7 +390,7 @@ You can nest the `InfoWindow` component inside the `Marker` component to display -
+

Uluru

@@ -431,6 +431,44 @@ export default defineComponent({ ``` +#### Open and close the Info Window + +You can use `v-model` to manage the state of the info window programmatically or to know whether it's open or closed + +```vue + + + +``` + #### Events You can listen for [the following events](https://developers.google.com/maps/documentation/javascript/reference/info-window#InfoWindow-Events) on the `InfoWindow` component. diff --git a/docs/components/info-window.md b/docs/components/info-window.md index 42327e5..9a05733 100644 --- a/docs/components/info-window.md +++ b/docs/components/info-window.md @@ -60,7 +60,7 @@ You can nest the `InfoWindow` component inside the `Marker` component to display > -
+

Uluru

@@ -102,7 +102,7 @@ export default defineComponent({ -
+

Uluru

@@ -125,6 +125,62 @@ https://en.wikipedia.org/w/index.php?title=Uluru + +## Use with vModel + +You can use v-model on the `InfoWindow` to manage it's open/closed state + + +```vue + + + +``` + ## Events You can listen for [the following events](https://developers.google.com/maps/documentation/javascript/reference/info-window#InfoWindow-Events) on the `InfoWindow` component. diff --git a/package.json b/package.json index b441fbe..1110b3e 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ }, "scripts": { "dev": "vite", + "prepare": "pnpm run build", "clean": "rimraf dist/**/*", "lint": "npx eslint --ext .ts,.vue src dev docs --fix", "build:umd": "node ./scripts/build-umd.js", @@ -56,6 +57,7 @@ "fast-deep-equal": "^3.1.3" }, "devDependencies": { + "pnpm": "^8.7.6", "@types/google.maps": "^3.53.6", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", @@ -77,7 +79,7 @@ "vue-tsc": "^1.8.8" }, "peerDependencies": { - "vue": "^3.3.4" + "vue": "^3" }, "engines": { "node": ">=16.11.0" diff --git a/src/components/InfoWindow.vue b/src/components/InfoWindow.vue index 68bd60a..b1c2680 100644 --- a/src/components/InfoWindow.vue +++ b/src/components/InfoWindow.vue @@ -32,9 +32,12 @@ export default defineComponent({ type: Object as PropType, default: () => ({}), }, + modelValue: { + type: Boolean, + }, }, - emits: infoWindowEvents, + emits: [...infoWindowEvents, "update:modelValue"], setup(props, { slots, emit, expose }) { const infoWindow = ref(); @@ -44,12 +47,28 @@ export default defineComponent({ const api = inject(apiSymbol, ref()); const anchor = inject(markerSymbol, ref()); let anchorClickListener: google.maps.MapsEventListener; + let internalVal = props.modelValue; // Doesn't need to be reactive const hasSlotContent = computed(() => slots.default?.().some((vnode) => vnode.type !== Comment)); - const open = (opts?: google.maps.InfoWindowOpenOptions) => - infoWindow.value?.open({ map: map.value, anchor: anchor.value, ...opts }); - const close = () => infoWindow.value?.close(); + const updateVModel = (val: boolean) => { + internalVal = val; + emit('update:modelValue', val); + } + + const open = (opts?: google.maps.InfoWindowOpenOptions) => { + if (infoWindow.value) { + infoWindow.value.open({ map: map.value, anchor: anchor.value, ...opts }); + updateVModel(true); + } + }; + + const close = () => { + if (infoWindow.value) { + infoWindow.value.close(); + updateVModel(false); + } + }; onMounted(() => { watch( @@ -77,13 +96,16 @@ export default defineComponent({ anchorClickListener = anchor.value.addListener("click", () => { open(); }); - } else { + } + + if (!anchor.value || internalVal) { open(); } infoWindowEvents.forEach((event) => { infoWindow.value?.addListener(event, (e: unknown) => emit(event, e)); }); + infoWindow.value?.addListener('closeclick', () => updateVModel(false)); } } }, @@ -91,6 +113,12 @@ export default defineComponent({ immediate: true, } ); + + watch(() => props.modelValue, (val) => { + if (val !== internalVal) { + val ? open() : close(); + } + }); }); onBeforeUnmount(() => {