Last active
October 8, 2015 02:39
-
-
Save jgaskins/839ec56cad03306fb93b to your computer and use it in GitHub Desktop.
Using virtual-dom hooks to render a Google Map in Clearwater
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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