Created
October 5, 2015 03:51
-
-
Save jgaskins/5bfe94ba62eb6ba4c52b to your computer and use it in GitHub Desktop.
Widgets with 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 'clearwater/component' | |
require 'google_map_container' | |
class Foo | |
include Clearwater::Component | |
def render | |
GoogleMapContainer.new( | |
height: 500, | |
width: 500, | |
# Baltimore | |
latitude: 39.287858, | |
longitude: -76.613702, | |
zoom: 13, | |
) | |
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
class GoogleMapContainer < Widget | |
attr_reader :map | |
def initialize(height:, width:, latitude: 0, longitude: 0, zoom: 13) | |
@height = height | |
@width = width | |
@latitude = latitude | |
@longitude = longitude | |
@zoom = zoom | |
end | |
def mount | |
@map = %x{ | |
new google.maps.Map(#{element}, { | |
center: new google.maps.LatLng(#@latitude, #@longitude), | |
zoom: #@zoom, | |
}) | |
} | |
end | |
# Copy the map from the previous instance. This is important if we want to do anything | |
# with it. | |
def update prev, dom_node | |
@map = prev.map | |
end | |
def unmount | |
@map = nil | |
end | |
# Override the node being provided. We want to ensure it has a height and width because | |
# Google Maps won't set it. | |
def node | |
VirtualDOM.node('div', { | |
style: { | |
height: "#{@height}px", | |
width: "#{@width}px", | |
}, | |
}) | |
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
class Widget | |
attr_reader :element | |
def self.new(*args, &block) | |
widget = super | |
# virtual-dom handles "Widgets" in a special way | |
widget.instance_exec { @type = 'Widget' } | |
widget | |
end | |
# The mount method is called when the widget is inserted into the DOM. You'll | |
# want to run any setup here, such as attaching a Google Map | |
def mount | |
end | |
# The update method is called when we render a new widget in place of another. | |
# Any state initialized in the mount method will need to be migrated to this | |
# instance of the widget. | |
# | |
# previous: the widget this one will be replacing | |
# dom_node: the DOM node this object is being mounted into | |
def update previous, dom_node | |
end | |
# The unmount method is called when the widget is removed from the DOM. | |
# We'll need to get rid of the Google Map or chart or whatever we're working with. | |
def unmount | |
end | |
def new_element | |
# I had to add this method. | |
VirtualDOM.create_element(node) | |
end | |
def node | |
VirtualDOM.node('div') | |
end | |
# These are the JS-native virtual-dom Widget callbacks. We delegate to the Ruby versions | |
# so they can be overridden easily. | |
%x{ | |
Opal.defn(self, 'init', function() { | |
var self = this; | |
self.element = self.$new_element(); | |
#{mount}; | |
return self.element; | |
}); | |
Opal.defn(self, 'update', function(prev, dom_node) { | |
var self = this; | |
self.element = dom_node; | |
#{update(`prev`, Opal::Browser::DOM::Element.new(`dom_node`))}; | |
}); | |
Opal.defn(self, 'destroy', function() { | |
var self = this; | |
delete self.element; | |
#{unmount}; | |
}); | |
} | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment