Module: Spark::Component::Element::ClassMethods

Defined in:
lib/spark/component/element.rb

Instance Method Summary collapse

Instance Method Details

#define_element(name:, plural:, multiple:, klass:) ⇒ Object

Element method will create a new element instance, or if no attributes or block is passed it will return the instance defined for that element.

For example when rendering a component, passing attributes or a block will create a new instance of that element.

# Some view (Slim)
= render(Nav) do |nav|
  - nav.item(href: "#url") { "link text" }

Then when referencing the element in the component’s template it the method will return the instance. Call yield to output an elemnet’s block

# Nav template (Slim)
nav
  - items.each do |item|
    a href=item.href
      = item.yield


186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/spark/component/element.rb', line 186

def define_element(name:, plural:, multiple:,  klass:)
  define_method_if_able(name) do |attributes = nil, &block|
    # When initializing an element, blocks or arguments are passed.
    # If an element is being referenced without these, it will return its instance
    # This allows the elemnet method to initailize the object and return its instance
    # for template rendering.
    unless block || attributes

      # If an element is called, it will only exist if its parent's block has been exectued
      # Be sure the block has been executed so that sub elements are initialized
      self.yield if is_a?(Spark::Component::Element::Base) && !rendered?

      return get_element_variable(multiple ? plural : name)
    end

    attributes ||= {}
    attributes = merge_element_attribute_default(name, attributes)
    attributes.merge!(_name: name, _parent: self, _block: block, _view: view_context)

    element = klass.new(attributes)

    # If element supports multiple instances, inject instance
    # into array for later enumeration
    if multiple
      get_element_variable(plural) << element
    else
      set_element_variable(name, element)
    end
  end

  return if !multiple || name == plural

  # Define a pluralized method name to access enumerable element instances.
  define_method_if_able(plural) do
    get_element_variable(plural)
  end
end

#element(name, multiple: false, component: nil, &config) ⇒ Object

Class method for adding elements

Options:

name: Symbol

  Create a method for interacting with an element
  This name cannot be the same as another instance method

multiple: Boolean (default: false)

  Defining `multiple: true` causes elements to be injected
  into an array. A pluralized method is created to access
  each element instance.

  For example, `element(:item, multiple: true)` will create
  an `:items` method and each time an item is executed, its
  instance will be added to items.

component: Class

  By default all elements include Element and extend its class methods
  Passing a class like `component: Nav::Item` will extend that component
  adding Element, Attributes, TagAttr and render methods.

&config: Block

  When defining a method, you may pass an optional block to
  configure attributes, nested elements, or even define methods.


157
158
159
160
161
162
163
# File 'lib/spark/component/element.rb', line 157

def element(name, multiple: false, component: nil, &config)
  plural_name = name.to_s.pluralize.to_sym if multiple
  klass = extend_class(component, &config)
  elements[name] = { multiple: plural_name, class: klass }

  define_element(name: name, plural: plural_name, multiple: multiple, klass: klass)
end

#elementsObject



123
124
125
# File 'lib/spark/component/element.rb', line 123

def elements
  @elements ||= {}
end

#inherited(child) ⇒ Object



114
115
116
117
118
119
120
121
# File 'lib/spark/component/element.rb', line 114

def inherited(child)
  child.elements.replace(elements)
  child.attributes.replace(attributes)
  child.tag_attributes.replace(tag_attributes)
  child.data_attributes.replace(data_attributes)
  child.aria_attributes.replace(aria_attributes)
  child.attribute_default_groups.replace(attribute_default_groups)
end