The code is split in two files. The first one, where I bind the functions:
[...]
[@bs.new] [@bs.scope ("google", "maps")] external makeMap : Dom.element => mapOptions => map = "Map";
[@bs.new] [@bs.scope ("google", "maps")] external makeMarker : markerOptions => marker = "Marker";
[@bs.new] [@bs.scope ("google", "maps")] external makeInfoWindow : infoWindowOptions => infoWindow = "infoWindow";
[@bs.val] [@bs.scope ("infoWindow")] external openInfoWindow : map => marker => unit = "open";
let initMap = () => {
APISpots.renderByQuery(".una-reason__spots", ~context={
map: makeMap,
marker: makeMarker,
infoWindow: makeInfoWindow,
openInfoWindow,
});
};
[%bs.raw {| window.initMap = initMap |}];
The functions are then passed to a ReasonReact component, that use them as follows:
[...]
module Models {
type coordinates = {. "lat": float, "lng": float};
type map;
type mapOptions = {.
"center": coordinates,
"zoom": int
};
type marker;
type markerOptions = {.
"title": string,
"position": coordinates,
"map": map,
};
type infoWindow;
type infoWindowOptions = {.
"content": string,
};
type context = {
map: Dom.element => mapOptions => map,
marker: markerOptions => marker,
infoWindow: infoWindowOptions => infoWindow,
openInfoWindow: map => marker => unit,
};
};
[...]
didUpdate: _ => {
let {Models.map, Models.marker, Models.infoWindow, Models.openInfoWindow} = switch(context) {
| Some(fn) => fn
| None => raise(NoFunction("You may pass Google Maps Javascript API context through `context` prop!"))
};
let el = Utils.DOM.getElementById("una-the-map");
let m = map(el, {
"center": {
"lat": float_of_string(latitude),
"lng": float_of_string(longitude),
},
"zoom": zoom,
});
let spots = switch (spots) {
| Some(spots) => spots
| None => []
};
let markers = spots
|> List.filter(spot => spot.latitude !== None && spot.longitude !== None)
|> List.map(spot => marker({
"position": {
"lat": float_of_string(Js.Option.getExn(spot.latitude)),
"lng": float_of_string(Js.Option.getExn(spot.longitude)),
},
"map": m,
"title": spot.display_name,
})
);
let iw = infoWindow({
"content": "Lorem Ipsum",
});
openInfoWindow(m, markers |> List.hd);
();
},
[...]
I think it’s enough for you to have an idea, as the rest of the code doesn’t use the binded functions.
The map and marker functions worked with no problem, also infoWindow raised no error until I bound infoWindow.close the way you suggested.