Open sebyx07 opened 4 years ago
I'll leave application_component.rb
class ApplicationComponent < ViewComponentReflex::Component
end
& the example_component.rb just in case
module My
class ExampleComponent < ApplicationComponent
attr_accessor :count
def initialize
@count = 1
end
def increment
self.count += 1
end
end
end
& the html
<%= component_controller do %>
<p><%= count %></p>
<%= reflex_tag :increment, :button, "Click" %>
<% end %>
Following @sebyx07 approach I modified stimulus controller naming resolvers to match following "sidecar" folder structure.
Assuming we have a parent_component
with nested first_child_component
I wanted to have:
app/components/
├- parent_component.rb
└- parent_component/
├- parent_controller.js
├- parent_component.html.erb
├- first_child_component.rb
└- first_child_component/
├- first_child_controller.js
└- first_child_component.html.erb
I had to modify getDefinitionsFromContext
function in order to remove all _component
parts from filenames and to follow stimulus naming conventions ("--" for namespace separation and "-" for word separation):
const cvContext = require.context("../../components", true, /_controller\.js$/)
function getDefinitionsFromContext(ctx){
return ctx.keys().map((path) => {
const splitPath = path.split("/");
const identifier = splitPath.slice(1, splitPath.length - 1).join("--").replace(/_component/g, "").replace('_', '-');
const obj = ctx(path);
const klassKey = Object.keys(obj)[0];
const controllerConstructor = obj[klassKey];
return {
identifier,
controllerConstructor
};
});
}
application.load(getDefinitionsFromContext(cvContext))
and override self.stimulus_controller
method from ViewComponentReflex::Component
module to:
ViewComponentReflex::Component.module_eval do
def self.stimulus_controller
name.gsub('Component', '').underscore.dasherize.gsub("/", "--")
end
end
This approach allowed component_controller
helper method to generate following controllers:
...
<div data-controller="parent" key="123"></div>
...
<div data-controller="parent--first-child" key="456"></div>
...
and to be properly initialized by Stimulus framework.
This is how I use view_component_reflex with the --sidecar layout from view_component.
first the dir structure
Before putting the .js & .scss you must change the application.js to load controllers properly. Here is mine:
My application_controller.js, which is pretty standard
I'll skip example_component.rb, example_component.html.erb because they are standard
Here is the example_component_controller.js, which also links the .scss file
import "./example_component.scss" import ApplicationController from "../../../javascript/controllers/application_controller";
finally the .scss which is scoped to this component, nothing fancy, but usefull
Would be cool if someone will write a generator for this so we could just
rails g component my_awesome/nested_component