Skip to content

Commit

Permalink
feat: add v-model to infowindow
Browse files Browse the repository at this point in the history
  • Loading branch information
Tofandel authored Sep 26, 2023
1 parent b52d877 commit 64ac3ac
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 10 deletions.
42 changes: 40 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Include the following script tag in your `index.html` (make sure to include it a
<script src="https://unpkg.com/vue3-google-map"></script>
```

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)

Expand Down Expand Up @@ -390,7 +390,7 @@ You can nest the `InfoWindow` component inside the `Marker` component to display
<GoogleMap api-key="YOUR_GOOGLE_MAPS_API_KEY" style="width: 100%; height: 500px" :center="center" :zoom="4">
<Marker :options="{ position: center }">
<InfoWindow>
<div id="contet">
<div id="content">
<div id="siteNotice"></div>
<h1 id="firstHeading" class="firstHeading">Uluru</h1>
<div id="bodyContent">
Expand Down Expand Up @@ -431,6 +431,44 @@ export default defineComponent({
</script>
```

#### 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
<template>
<GoogleMap api-key="YOUR_GOOGLE_MAPS_API_KEY" style="width: 100%; height: 500px" :center="center" :zoom="4">
<Marker :options="{ position: center }">
<InfoWindow v-model="infowindow">
<div id="content">
This is the infowindow content
</div>
</InfoWindow>
</Marker>
</GoogleMap>
</template>
<script>
import { defineComponent } from "vue";
import { GoogleMap, Marker, InfoWindow } from "vue3-google-map";
export default defineComponent({
components: { GoogleMap, Marker, InfoWindow },
setup() {
const center = { lat: -25.363, lng: 131.044 };
const infowindow = ref(true); // Will be opened when mounted
return { center, infowindow };
},
watch: {
infowindow(v) {
alert('infowindow has been ' + (v ? 'opened' : 'closed'))
}
}
});
</script>
```

#### Events

You can listen for [the following events](https://developers.google.com/maps/documentation/javascript/reference/info-window#InfoWindow-Events) on the `InfoWindow` component.
Expand Down
60 changes: 58 additions & 2 deletions docs/components/info-window.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ You can nest the `InfoWindow` component inside the `Marker` component to display
>
<Marker :options="{ position: center }">
<InfoWindow>
<div id="contet">
<div id="content">
<div id="siteNotice"></div>
<h1 id="firstHeading" class="firstHeading">Uluru</h1>
<div id="bodyContent">
Expand Down Expand Up @@ -102,7 +102,7 @@ export default defineComponent({
<GoogleMap style="width: 100%; height: 500px" :center="{ lat: -25.363, lng: 131.044 }" :zoom="4">
<Marker :options="{ position: { lat: -25.363, lng: 131.044 } }">
<InfoWindow>
<div id="contet">
<div id="content">
<div id="siteNotice"></div>
<h1 id="firstHeading" class="firstHeading">Uluru</h1>
<div id="bodyContent">
Expand All @@ -125,6 +125,62 @@ https://en.wikipedia.org/w/index.php?title=Uluru</a>
</Marker>
</GoogleMap>


## Use with vModel

You can use v-model on the `InfoWindow` to manage it's open/closed state

<!-- prettier-ignore -->
```vue
<template>
<GoogleMap
api-key="YOUR_GOOGLE_MAPS_API_KEY"
style="width: 100%; height: 500px"
:center="center"
:zoom="4"
>
<Marker :options="{ position: center }">
<InfoWindow v-model="infoWindow">
<div id="content">
<div id="siteNotice"></div>
<h1 id="firstHeading" class="firstHeading">Uluru</h1>
<div id="bodyContent">
<p><b>Uluru</b>, also referred to as <b>Ayers Rock</b>, is a large
sandstone rock formation in the southern part of the
Northern Territory, central Australia. It lies 335&#160;km (208&#160;mi)
south west of the nearest large town, Alice Springs; 450&#160;km
(280&#160;mi) by road. Kata Tjuta and Uluru are the two major
features of the Uluru - Kata Tjuta National Park. Uluru is
sacred to the Pitjantjatjara and Yankunytjatjara, the
Aboriginal people of the area. It has many springs, waterholes,
rock caves and ancient paintings. Uluru is listed as a World
Heritage Site.</p>
<p>Attribution: Uluru, <a href="https://en.wikipedia.org/w/index.php?title=Uluru&oldid=297882194">
https://en.wikipedia.org/w/index.php?title=Uluru</a>
(last visited June 22, 2009).</p>
</div>
</div>
</InfoWindow>
</Marker>
</GoogleMap>
</template>
<script>
import { defineComponent, ref } from 'vue'
import { GoogleMap, Marker, InfoWindow } from 'vue3-google-map'
export default defineComponent({
components: { GoogleMap, Marker, InfoWindow },
setup() {
const center = { lat: -25.363, lng: 131.044 }
const infoWindow = ref(true); // Open by default
return { center, infoWindow }
},
})
</script>
```

## Events

You can listen for [the following events](https://developers.google.com/maps/documentation/javascript/reference/info-window#InfoWindow-Events) on the `InfoWindow` component.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -77,7 +79,7 @@
"vue-tsc": "^1.8.8"
},
"peerDependencies": {
"vue": "^3.3.4"
"vue": "^3"
},
"engines": {
"node": ">=16.11.0"
Expand Down
38 changes: 33 additions & 5 deletions src/components/InfoWindow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ export default defineComponent({
type: Object as PropType<google.maps.InfoWindowOptions>,
default: () => ({}),
},
modelValue: {
type: Boolean,
},
},
emits: infoWindowEvents,
emits: [...infoWindowEvents, "update:modelValue"],
setup(props, { slots, emit, expose }) {
const infoWindow = ref<google.maps.InfoWindow>();
Expand All @@ -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(
Expand Down Expand Up @@ -77,20 +96,29 @@ 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));
}
}
},
{
immediate: true,
}
);
watch(() => props.modelValue, (val) => {
if (val !== internalVal) {
val ? open() : close();
}
});
});
onBeforeUnmount(() => {
Expand Down

0 comments on commit 64ac3ac

Please sign in to comment.