Skip to content

Instantly share code, notes, and snippets.

@jgaskins
Last active October 8, 2015 02:39
Show Gist options
  • Save jgaskins/839ec56cad03306fb93b to your computer and use it in GitHub Desktop.
Save jgaskins/839ec56cad03306fb93b to your computer and use it in GitHub Desktop.
Using virtual-dom hooks to render a Google Map in Clearwater
require 'browser/animation_frame'
require 'hook'
class GoogleMapRenderer
include Hook
def initialize(latitude: 0, longitude: 0, zoom: 13)
@latitude = latitude
@longitude = longitude
@zoom = zoom
end
def mount node
# Run on the next animation frame because we have to wait until after the
# container is mounted into the DOM. This method is actually called on a DOM
# node in memory when first mounted. This might be specific to Google Maps.
animation_frame do
@map = %x{
new google.maps.Map(node.native, {
center: new google.maps.LatLng(#@latitude, #@longitude),
zoom: #@zoom,
})
}
end
end
end
module Hook
def self.included base
# Add the hook property to the component.
%x{
Opal.defn(base, 'hook', function(node) {
var self = this;
#{mount(Browser::DOM::Element.new(`node`))};
});
}
end
# This method is called when the component that uses this hook gets converted
# from a VNode into an actual-DOM node. Override it in your implementation.
def mount node
end
end
require 'clearwater/component'
require 'clearwater/cached_render'
require 'google_map_renderer'
class Map
include Clearwater::Component
# Important to cache the render here. Otherwise, it'll re-render a Google Map
# every time your app is rendered with this component in it, eating up your
# Google Map quota. You do want it to re-render when this component is
# inserted back into the DOM and this will do that.
include Clearwater::CachedRender
def render
div(
# Give this a unique key so if this component is removed from the virtual
# DOM, this div won't stay in the actual DOM.
key: 'google-map',
style: {
height: '500px',
width: '600px',
},
# The weird thing about virtual-dom hooks is that it doesn't matter what the
# attribute name is. All it cares is that the value quacks like a virtual-dom
# hook.
map_renderer: GoogleMapRenderer.new(
latitude: 39.287858,
longitude: -76.613702,
zoom: 13,
)
)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment