Skip to content

Commit 5330ad3

Browse files
committed
Updated plugin development documentation
1 parent 67d3bfb commit 5330ad3

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed

docs_source/plugin_components/plugin_components_development.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,124 @@ Example below can give you an idea how to create component for Mapbox GL JS plug
121121

122122
**[VueMaboxGeocoder](https://github.com/soal/vue-mapbox-geocoder) — wrapper for [mapbox-gl-geocoder](https://github.com/mapbox/mapbox-gl-geocoder)**:
123123

124+
```js
125+
// First, there is no separate HTML to render, so we don't need template and SFC, so it's just JS file
126+
127+
import MapboxGeocoder from "@mapbox/mapbox-gl-geocoder";
128+
import { $helpers } from "vue-mapbox"; // Get $helpers from VueMapbox
129+
130+
// Define list of mapbox-gl-geocoder events
131+
const geocoderEvents = {
132+
clear: "clear",
133+
loading: "loading",
134+
results: "results",
135+
result: "result",
136+
error: "error"
137+
};
138+
139+
export default {
140+
name: "GeocoderControl",
141+
mixins: [$helpers.asControl], // MapboxGeocoder is a control, so we use mixin
142+
143+
inject: ["mapbox", "map"], // Here we inject objects provided by MglMap
144+
145+
props: {
146+
// MapboxGeocoder requires access token
147+
accessToken: {
148+
type: String,
149+
required: true
150+
},
151+
input: {
152+
type: String,
153+
default: null
154+
},
155+
proximity: {
156+
type: Object,
157+
default: null
158+
}
159+
// ...here goes other props...
160+
},
161+
162+
data() {
163+
return {
164+
initial: true
165+
};
166+
},
167+
168+
// Here we watch for props and and apply changes to MapboxGeocoder if needed
169+
watch: {
170+
input: {
171+
handler(next, prev) {
172+
if (this.control && next !== prev) {
173+
this.control.setInput(next);
174+
}
175+
},
176+
immediate: true
177+
},
178+
proximity(next, prev) {
179+
if (this.control && next !== prev) {
180+
this.control.setProximity(next);
181+
}
182+
}
183+
},
184+
185+
created() {
186+
this.control = null; // Here we will store MapboxGeocoder instance. We don't want Vue reactivity system mess with it, so we store it non-reactive
187+
if (this.accessToken && !this.mapbox.accessToken) {
188+
this.mapbox.accessToken = this.accessToken;
189+
}
190+
this.control = new MapboxGeocoder(this.$props); // Creating MapboxGeocoder instance and pass props as options to it
191+
this.control.on("results", this.$_updateInput); // We need to update synchronized prop "input" when user enters some query to search field
192+
193+
// Now we can add control to the map
194+
this.$_deferredMount();
195+
},
196+
197+
beforeDestroy() {
198+
this.control.off("results", this.$_updateInput);
199+
// Also, control will be removed from map in beforeDestroy() lifecycle hook in `asControl` mixin
200+
},
201+
202+
methods: {
203+
$_deferredMount() {
204+
// Because this component placed in MglMap sub-tree, map already initialized and injected above
205+
this.map.addControl(this.control);
206+
if (this.input) {
207+
// Set input in MapboxGeocoder if there is default data
208+
this.control.setInput(this.input);
209+
}
210+
// Emit added event. `$_emitEvent` method is came from `asControl` mixin
211+
this.$_emitEvent("added", { geocoder: this.control });
212+
this.$_bindSelfEvents(Object.keys(geocoderEvents)); // Bin events to emit them as Vue events
213+
this.initial = false; // Initialization done
214+
},
215+
216+
$_bindSelfEvents(events) {
217+
// $_bindSelfEvents is provided by `asControl` mixin. but we need to replace it because MapboxGeocoder do not follow Mapbox Gl JS events schema and we need custom processing for them
218+
const vm = this;
219+
// Here we use this.$listeners to subscribe only on events that user listens on component
220+
Object.keys(this.$listeners).forEach(eventName => {
221+
if (events.includes(eventName)) {
222+
this.control.on(eventName, vm.$_emitControlEvent.bind(vm, eventName));
223+
}
224+
});
225+
},
226+
227+
// Process event to line up with VueMapbox events format
228+
$_emitControlEvent(eventName, eventData) {
229+
return this.$_emitSelfEvent({ type: eventName }, eventData);
230+
},
231+
232+
$_updateInput(results) {
233+
if (!this.initial) {
234+
const input = results.query ? results.query.join("") : "";
235+
this.$emit("update:input", input); // update synchormized prop "input"
236+
}
237+
}
238+
239+
//...here goes other public methods
240+
}
241+
};
242+
```
243+
124244
<!-- ## Component API recommendations -->

0 commit comments

Comments
 (0)