Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save AndyObtiva/2faaf534b3bd3567cd18fb1c2663f97b to your computer and use it in GitHub Desktop.
Save AndyObtiva/2faaf534b3bd3567cd18fb1c2663f97b to your computer and use it in GitHub Desktop.
Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework) Hello, Component Slots! Sample
require 'glimmer-dsl-web'
Address = Struct.new(:full_name, :street, :street2, :city, :state, :zip_code, :billing_and_shipping, keyword_init: true) do
STATES = {
"AK"=>"Alaska", "AL"=>"Alabama", "AR"=>"Arkansas", "AS"=>"American Samoa", "AZ"=>"Arizona",
"CA"=>"California", "CO"=>"Colorado", "CT"=>"Connecticut", "DC"=>"District of Columbia", "DE"=>"Delaware",
"FL"=>"Florida", "GA"=>"Georgia", "GU"=>"Guam", "HI"=>"Hawaii", "IA"=>"Iowa", "ID"=>"Idaho", "IL"=>"Illinois",
"IN"=>"Indiana", "KS"=>"Kansas", "KY"=>"Kentucky", "LA"=>"Louisiana", "MA"=>"Massachusetts", "MD"=>"Maryland",
"ME"=>"Maine", "MI"=>"Michigan", "MN"=>"Minnesota", "MO"=>"Missouri", "MS"=>"Mississippi", "MT"=>"Montana",
"NC"=>"North Carolina", "ND"=>"North Dakota", "NE"=>"Nebraska", "NH"=>"New Hampshire", "NJ"=>"New Jersey",
"NM"=>"New Mexico", "NV"=>"Nevada", "NY"=>"New York", "OH"=>"Ohio", "OK"=>"Oklahoma", "OR"=>"Oregon",
"PA"=>"Pennsylvania", "PR"=>"Puerto Rico", "RI"=>"Rhode Island", "SC"=>"South Carolina", "SD"=>"South Dakota",
"TN"=>"Tennessee", "TX"=>"Texas", "UT"=>"Utah", "VA"=>"Virginia", "VI"=>"Virgin Islands", "VT"=>"Vermont",
"WA"=>"Washington", "WI"=>"Wisconsin", "WV"=>"West Virginia", "WY"=>"Wyoming"
}
def state_code
STATES.invert[state]
end
def state_code=(value)
self.state = STATES[value]
end
def summary
string_attributes = to_h.except(:billing_and_shipping)
summary = string_attributes.values.map(&:to_s).reject(&:empty?).join(', ')
summary += " (Billing & Shipping)" if billing_and_shipping
summary
end
end
# AddressForm Glimmer Web Component (View component)
#
# Including Glimmer::Web::Component makes this class a View component and automatically
# generates a new Glimmer HTML DSL keyword that matches the lowercase underscored version
# of the name of the class. AddressForm generates address_form_with_slots keyword, which can be used
# elsewhere in Glimmer HTML DSL code as done inside HelloComponentSlots below.
class AddressFormWithSlots
include Glimmer::Web::Component
option :address
# markup block provides the content of the
markup {
div {
# designate this div as a slot with the slot name :address_header to enable
# consumers to contribute elements to `address_header {...}` slot
div(slot: :address_header, class: 'address-form-header')
div(class: 'address-field-container', style: {display: :grid, grid_auto_columns: '80px 260px'}) {
label('Full Name: ', for: 'full-name-field')
input(id: 'full-name-field') {
value <=> [address, :full_name]
}
@somelabel = label('Street: ', for: 'street-field')
input(id: 'street-field') {
value <=> [address, :street]
}
label('Street 2: ', for: 'street2-field')
textarea(id: 'street2-field') {
value <=> [address, :street2]
}
label('City: ', for: 'city-field')
input(id: 'city-field') {
value <=> [address, :city]
}
label('State: ', for: 'state-field')
select(id: 'state-field') {
Address::STATES.each do |state_code, state|
option(value: state_code) { state }
end
value <=> [address, :state_code]
}
label('Zip Code: ', for: 'zip-code-field')
input(id: 'zip-code-field', type: 'number', min: '0', max: '99999') {
value <=> [address, :zip_code,
on_write: :to_s,
]
}
}
div(style: {margin: 5}) {
inner_text <= [address, :summary,
computed_by: address.members + ['state_code'],
]
}
# designate this div as a slot with the slot name :address_footer to enable
# consumers to contribute elements to `address_footer {...}` slot
div(slot: :address_footer, class: 'address-form-footer')
}
}
style {
r('.address-field-container *') {
margin 5
}
r('.address-field-container input, .address-field-container select') {
grid_column '2'
}
}
end
# HelloComponentSlots Glimmer Web Component (View component)
#
# This View component represents the main page being rendered,
# as done by its `render` class method below
class HelloComponentSlots
include Glimmer::Web::Component
before_render do
@shipping_address = Address.new(
full_name: 'Johnny Doe',
street: '3922 Park Ave',
street2: 'PO BOX 8382',
city: 'San Diego',
state: 'California',
zip_code: '91913',
)
@billing_address = Address.new(
full_name: 'John C Doe',
street: '123 Main St',
street2: 'Apartment 3C',
city: 'San Diego',
state: 'California',
zip_code: '91911',
)
end
markup {
div {
address_form_with_slots(address: @shipping_address) {
address_header { # contribute elements to the address_header component slot
h1('Shipping Address')
legend('This is the address that is used for shipping your purchase.', style: {margin_bottom: 10})
}
address_footer { # contribute elements to the address_footer component slot
p(sub("#{strong('Note:')} #{em('Purchase will be returned if the Shipping Address does not accept it in one week.')}"))
}
}
address_form_with_slots(address: @billing_address) {
address_header { # contribute elements to the address_header component slot
h1('Billing Address')
legend('This is the address that is used for your billing method (e.g. credit card).', style: {margin_bottom: 10})
}
address_footer { # contribute elements to the address_footer component slot
p(sub("#{strong('Note:')} #{em('Payment will fail if payment method does not match the Billing Address.')}"))
}
}
}
}
end
Document.ready? do
# renders a top-level (root) HelloComponentSlots component
HelloComponentSlots.render
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment