Skip to content
This repository has been archived by the owner on Oct 19, 2018. It is now read-only.

need way to dynamically mount components (i.e. after ajax calls) #252

Open
catmando opened this issue Feb 20, 2018 · 2 comments
Open

need way to dynamically mount components (i.e. after ajax calls) #252

catmando opened this issue Feb 20, 2018 · 2 comments

Comments

@catmando
Copy link
Contributor

catmando commented Feb 20, 2018

require 'jquery'
require 'opal-jquery'

module Hyperloop
  def self.mount_all
    Element['[data-hyperloop-mount]'].each do |mount_point|
      component_name = mount_point.attr('data-hyperloop-mount')
      component = nil
      begin
        component = Object.const_get(component_name)
      rescue
        message = "Could not find Component class named #{component_name}"
        `console.error(message)`
        next
      end
      params = Hash[*mount_point.data.collect do |name, value|
        [name.underscore, value] unless name == 'hyperloopMount'
      end.compact.flatten(1)]
      React.render(React.create_element(component, params), mount_point)
    end
  end
  %x{
     window.hyperloop_mount_all = function() {
       #{Hyperloop.mount_all}
      }
    }
end

From opal you can call Hyperloop.mount_all or from js land its hyperloop_mount_all()

It will find all components with the data-hyperloop-mount data attribute, and the name of the component will be the attribute value. For example

<DIV data-hyperloop-mount='MyBigComponent' data-param1='some data'>
</DIV>

will mount MyBigComponent at the DIV and pass it 'some data' as param1

@janbiedermann
Copy link
Contributor

already there:

React::Test::Utils.render_component_into_document(MyComponent, args)

maybe needs a better name

@catmando
Copy link
Contributor Author

actually, its built into react-rails, and works with the <% react_component ...%> helper!

we can make it a bit nicer like this:

#jquery-mounter.rb
require 'jquery'
require 'opal-jquery'
%x{
  (function ( $ ) {
    $.fn.mount_components = function() {
      this.each(function(e) { ReactRailsUJS.mountComponents(e[0]) })
      return this;
    }
  }( jQuery ));
}
Element.expose :mount_components

Now we can add the components to the view using <%= react_component ... %> and mount them by doing a dom query, then calling mount_components.

Typical in JS:

// fetch.js.erb
$('#target_div').html("<%= escape_javascript(render partial: 'fetch') %>").mount_components();
// fetch.erb contains our html code including 1 or more component mount points

In Ruby

Element['body'].mount_components # mount everything!

catmando added a commit that referenced this issue May 5, 2018
aberios pushed a commit to rubyblackbelt/hyper-react that referenced this issue Jul 11, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants