class React::Element

Wraps the React Native element class

adds the on method to add event handlers to the element

adds the render method to place elements in the DOM and delete (alias/deprecated as_node) method to remove elements from the DOM

handles the haml style class notation so that

div.bar.blat becomes div(class: "bar blat")

by using method missing

Attributes

block[R]
properties[R]
type[R]
waiting_on_resources[RW]

Public Class Methods

haml_class_name(class_name) click to toggle source
# File lib/react/element.rb, line 93
def self.haml_class_name(class_name)
  class_name.gsub(/__|_/, '__' => '_', '_' => '-')
end
new(native_element, type, properties, block) click to toggle source
# File lib/react/element.rb, line 28
def initialize(native_element, type, properties, block)
  @type = type
  @properties = (`typeof #{properties} === 'undefined'` ? nil : properties) || {}
  @block = block
  @native = native_element
end

Public Instance Methods

as_node() click to toggle source

Deprecated version of delete method

# File lib/react/element.rb, line 68
def as_node
  React::RenderingContext.as_node(self)
end
delete() click to toggle source

Delete (remove) element from rendering context, the element may later be added back in using the render method.

# File lib/react/element.rb, line 62
def delete
  React::RenderingContext.delete(self)
end
method_missing(class_name, args = {}, &new_block) click to toggle source

Any other method applied to an element will be treated as class name (haml style) thus div.foo.bar(id: :fred) is the same as saying div(class: “foo bar”, id: :fred)

single underscores become dashes, and double underscores become a single underscore

params may be provide to each class (but typically only to the last for easy reading.)

# File lib/react/element.rb, line 79
def method_missing(class_name, args = {}, &new_block)
  return dup.render.method_missing(class_name, args, &new_block) unless rendered?
  React::RenderingContext.replace(
    self,
    RenderingContext.build do
      RenderingContext.render(type, build_new_properties(class_name, args), &new_block)
    end
  )
end
on(*event_names, &block) click to toggle source

Attach event handlers.

# File lib/react/element.rb, line 37
def on(*event_names, &block)
  event_names.each { |event_name| merge_event_prop!(event_name, &block) }
  @native = `React.cloneElement(#{to_n}, #{properties.shallow_to_n})`
  self
end
render(props = {}, &new_block) click to toggle source

Render element into DOM in the current rendering context. Used for elements that are not yet in DOM, i.e. they are provided as children or they have been explicitly removed from the rendering context using the delete method.

# File lib/react/element.rb, line 47
def render(props = {}, &new_block)
  if props.empty?
    React::RenderingContext.render(self)
  else
    props = API.convert_props(props)
    React::RenderingContext.render(
      Element.new(`React.cloneElement(#{to_n}, #{props.shallow_to_n})`,
                  type, properties.merge(props), block),
    )
  end
end
rendered?() click to toggle source
# File lib/react/element.rb, line 89
def rendered?
  React::RenderingContext.rendered? self
end

Private Instance Methods

build_new_properties(class_name, args) click to toggle source
# File lib/react/element.rb, line 99
def build_new_properties(class_name, args)
  class_name = self.class.haml_class_name(class_name)
  new_props = properties.dup
  new_props[:className] = "\
    #{class_name} #{new_props[:className]} #{args.delete(:class)} #{args.delete(:className)}\
  ".split(' ').uniq.join(' ')
  new_props.merge! args
end
merge_built_in_event_prop!(prop_name) click to toggle source
# File lib/react/element.rb, line 135
def merge_built_in_event_prop!(prop_name)
  @properties.merge!(
    prop_name => %x{
      function(event){
        return #{yield(React::Event.new(`event`))}
      }
    }
  )
end
merge_component_event_prop!(prop_name) click to toggle source
# File lib/react/element.rb, line 145
def merge_component_event_prop!(prop_name)
  @properties.merge!(
    prop_name => %x{
      function(){
        return #{yield(*Array(`arguments`))}
      }
    }
  )
end
merge_deprecated_component_event_prop!(event_name) click to toggle source
# File lib/react/element.rb, line 155
def merge_deprecated_component_event_prop!(event_name)
  prop_name = "_on#{event_name.event_camelize}"
  fn = %x{function(){#{
    React::Component.deprecation_warning(
      "In future releases React::Element#on('#{event_name}') will no longer respond "\
      "to the '#{prop_name}' emitter.\n"\
      "Rename your emitter param to 'on_#{event_name}' or use .on('<#{prop_name}>')"
    )}
    return #{yield(*Array(`arguments`))}
  }}
  @properties.merge!(prop_name => fn)
end
merge_event_prop!(event_name, &block) click to toggle source

built in events will have their event param translated to the Event wrapper and the name will camelcased and have on prefixed, so :click becomes onClick.

events emitting from native components are assumed to have the same camel case and on prefixed.

events emitting from reactrb components will just have on_ prefixed. So :play_button_pushed attaches to the :on_play_button_pushed param

in all cases the default name convention can be overriden by wrapping in <…> brackets. So on(“<MyEvent>”) will attach to the “MyEvent” param.

# File lib/react/element.rb, line 122
def merge_event_prop!(event_name, &block)
  if event_name =~ /^<(.+)>$/
    merge_component_event_prop! event_name.gsub(/^<(.+)>$/, '\1'), &block
  elsif React::Event::BUILT_IN_EVENTS.include?(name = "on#{event_name.event_camelize}")
    merge_built_in_event_prop! name, &block
  elsif @type.instance_variable_get('@native_import')
    merge_component_event_prop! name, &block
  else
    merge_deprecated_component_event_prop! event_name, &block
    merge_component_event_prop! "on_#{event_name}", &block
  end
end