Custom Component

Rules

  • The component must inherit the component element.
  • The component must meet the convention of the component.

Simple custom component

Content can be pass by variable (content) or by block (block).

Useful variables in render method:
  • content (content of component by variable or by block)
  • options (options of component)
  • html_options (html options of component)
Component.new(content = nil, options = {}, html_options = {}, &block).render

Component render: The component must use the render method to generate html code.

Structure

Useful methods to add default options and html options for a component:
  • component_html_classes
  • component_options
  • component_html_options
module UiBibz::Ui::Ux
  class MyComponent < UiBibz::Ui::Core::Component

    # Pre Render html
    def pre_render
      # Put your main code here, the pre_render method is called in the render method
      # The pre_render method exists to allow you to use the cache
    end

    private

    # Default component classes [String, Array] - This method is not required
    def component_html_classes
    end

    # Default component options [Hash] - This method is not required
    def component_options
    end

    # Default component html options [Hash] - This method is not required
    def component_html_options
    end

  end
end

Html classes structure

Several methods are called during the creation of html options classes:
  • state
  • status
  • effect
  • connect
  • component_html_classes
module UiBibz::Ui::Ux
  class MyComponent < UiBibz::Ui::Core::Component

    # Pre Render html
    def pre_render
    end

    private

    # To define state html class [:active, :disabled]
    def state
    end

    # To define status html class [primary, secondary, success, danger, warning, info, light, dark]
    def status
    end

    # To define effect html class
    def effect
    end

    # To define connect html class
    def connect
    end

    # To add classes to html classes
    def component_html_classes
    end

  end
end



Example 1

Create a ui folder in your application in app and put your components inside.

Creation of component

# app/ui/my_component.rb
module UiBibz::Ui::Ux
  class MyComponent < UiBibz::Ui::Core::Component

    def pre_render
      content_tag :div, html_options do
        link_to content, options[:url]
      end
    end

  end
end

Call custom Component

UiBibz::Ui::Ux::MyComponent.new('My link', { url: '/' }, { class: 'my-link'}).render
# or
UiBibz::Ui::Ux::MyComponent.new({ url: '/' }, { class: 'my-link'}) do
  "My link"
end.render
<div class='my-link'><a href='/'>My link</a></div>

Example 2

Creation of component

# app/ui/my_component.rb
module UiBibz::Ui::Ux
  class MyComponent2 < UiBibz::Ui::Core::Component

    def pre_render
      content_tag :div, html_options do
        link_to content, options[:url]
      end
    end

    private

    # Add default classes
    def component_html_classes
      ['my-class', status]
    end

    # Disabled component by default
    def component_options
      { state: :disabled } unless options[:state].nil
    end

    # Add html options data
    def component_html_data
      add_html_data('target', options[:target]) unless options[:target].nil?
    end

    # Add status class if status option is not nil
    def plugged
      "my-component-#{ options[:plugged] }" unless options[:plugged].nil?
    end

    # Method is called during the component html class creation
    def status
      "my-component-#{ options[:status] || :secondary }"
    end

  end
end



Create a helper

# app/helpers/component_helper.rb
def my_custom_component_2_helper content = nil, options = nil, html_options = nil, &block
  UiBibz::Ui::Ux::MyComponent2.new(content, options, html_options, block).render
end

Call custom helper

my_custom_component_2_helper('My link', { url: '/', plugged: true, target: '#target' }, { class: 'my-link'})
# or
my_custom_component_2_helper({ url: '/', plugged: true, target: '#target' }, { class: 'my-link'}) do
  'My link'
end
<div class='my-class my-component-plugged my-component-secondary my-link' data-target='#target'><a href='/'>My link</a></div>

Complex custom component

module UiBibz::Ui::Ux
  class MyComplexComponent < UiBibz::Ui::Core::Component

    # initialize component
    def initialize content = {}, options = {}, html_options = {}, &block
      super
      @items = []
    end

    # Render html
    def pre_render
      content_tag :div, @items.map(&:render).join.html_safe, html_options
    end

    # add links
    def link content = nil, options = nil, html_options = nil, &block
      @items << UiBibz::Ui::Core::Navigations::Link.new(content, options, html_options, &block)
    end

    private

    def component_html_classes
      "my-complex-component"
    end

  end
end

Create a helper

# app/helpers/component_helper.rb
def my_complex_component content = nil, options = nil, html_options = nil, &block
  UiBibz::Ui::Ux::MyComplexComponent.new(content, options, html_options).tap(&block).render
end

Call custom helper

my_complex_component class: 'my-class' do |cc|
  cc.link "Link1", url: "#link1", class: "me-2"
  cc.link url: "#link2" do
    Link 2
  end
end
<div class='my-class my-complex-component'>
  <a href='#link1' class="me-2">Link 1</a>
  <a href='#link2'>Link 2</a>
</div>

Tree architecture in your app

app
|_ ui
  |_ component_name.rb

# or

app
|_ui
  |_ component_name_folders
    |_ component_name.rb
    |_ components
      |_ sub_component_1.rb
      |_ sub_component_2.rb
Folder names must be named in plural.