Track your progress

Sign in to track your progress and access subscription-only lessons.

Log In

Your Teacher

Hey, I'm Adam! I spend my days coding and writing for Judoscale—the autoscaling service I created in 2016. I'm @adamlogic pretty much everywhere online.

About This Episode

Adam McCrea walks through using Phlex to build components for views in your Rails applications. Phlex is a Ruby gem for building fast object-oriented HTML and SVG components using Ruby constructs: methods, keyword arguments and blocks.

Notes

Resources

class AdapterSetupComponent < ApplicationComponent
  def initialize(app, process_type)
    @app = app
    @process_type = process_type
  end

  def template
    render ModalComponent.new do |modal|
      modal.parts do
        modal.header "Adapter Installation",
          previous_href:
            url_for([:new, @app, @process_type, :adapter_setup])

        modal.content do
          div(class: "p-8 prose max-w-none") do
            render "adapter_setups/languages/#{@app.language.downcase}"
          end
        end

        modal.footer do
          form_with model: @app,
            url: [@app, @process_type, :adapter_setup],
            method: :get,
            builder: StyledFormBuilder do |form|
            plain helpers.styled_button "Finished and Deployed",
              background: :gray,
              icon: "circlecheckmark"
          end
        end
      end
    end
  end
end
class ApplicationComponent < Phlex::HTML
  include Phlex::Rails::Helpers::Routes
  include Phlex::Rails::Helpers::ContentFor
  include Phlex::Rails::Helpers::LinkTo
  include Phlex::Rails::Helpers::FormWith

  if Rails.env.development?
    def before_template
      comment { "Before #{self.class.name}" }
      super
    end
  end
end
class ModalComponent < ApplicationComponent
  def template(dismissable: true, &block)
    content_for(:modal_content) do
      render "modals/modal_wrapper", dismissable: dismissable, &block
    end
  end

  def parts(hug: false, &block)
    # This wrappers assumes three child nodes (header, content, footer).
    div class: "grid grid-rows-[auto_1fr_auto] #{"min-h-[36rem]" unless hug}", &block
  end

  def header(title, dismissable: true, previous_href: nil)
    div(class: %(relative px-4 bg-gray-100 h-16 flex justify-center items-center)) {
      if previous_href
        link_to previous_href, class: "absolute left-4 text-gray-400 h-8 w-8" do
          plain helpers.svg(:chevronleft)
          div(class: %(sr-only)) {
            %(Back)
          }
        end
      end

      if dismissable
        button(type: %(button), class: %(absolute right-4 text-gray-400 h-8 w-8), "click.prevent": %(modalVisible = false)) {
          plain helpers.svg(:close)
        }
      end

      h2(class: %(text-gray-600 font-medium)) {
        title
      }
    }
  end

  def content(&block)
    div class: "max-h-[70vh] overflow-auto", &block
  end

  def footer(&block)
    div class: "relative p-4 bg-gray-100 flex justify-end items-center gap-4", &block
  end
end

Want to stay up-to-date with Ruby on Rails?

Join 80,973+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more.

    © 2024 GoRails, LLC. All rights reserved.