The page describes how to create a new UI component.
A fully functional example of source code you can find here
Steps
Create a component class
Create a class inherited fromApplicationComponent
underapp/components/
. By convention a class for a component must end in "Component". Add#initialize
method to the class.
def initialize(template, model)
super template
@model = model
end
Tips
- It is better if namespaces of a component and a related controller are similar. It is not required but it simplifies stuff.
- it is encouraged to create a related presenter class as a counterpart of a UI component. In this case a presenter is responsible for fetching data, including optimization concerns. At the same moment a component is responsible for: 1) rendering data, including formatting 2) handling details of WEB UI (for example how to translate names of request params to attributes of a presenter)
Example: component class
Create a view partial for a component
Create a partial file (/^_*.html.erb$/) underapp/views/components
. A file-path to just created view have to mimic namespacing of the component. For example if we haveFoo::Bar::BazComponent
, we have to createapp/views/components/foo/bar/_baz.html.erb
.
Example:partial
Instantiate a component object
Instantiate a component object usingApplicationController#new_component
method:
@baz = new_component(::Foo::Bar::BazComponent, @some_presenter)
Example: instantiation
Call #render
Render your component using inherited#render
method:
<%= @baz.render %>
Example: call render
Add JavaScript support (optional)
If your component depends on JS functionality, you should perform a few additional steps.
MixJsAware
module to your component.
module Foo
module Bar
class BazComponent < ApplicationComponent
include JsAware
...
Create JS file underapp/javascripts/main/components/
using the same approach to "namespacing" like for the view partial:app/javascripts/main/components/foo/bar/baz.js
A javascript object for a component should haveinit
method. Th method is call right after component is rendered.
window.foo = window.foo || {}
window.foo.bar = window.foo.bar || {}
window.foo.bar.Baz = (function () {
var c = {};
c.init = function (_opts) {
$('.baz-time').html(new Date().toString())
}
return c;
})();
Add newly created JS file to grunt.js. It is preferable to use wildcards:
'app/javascripts/main/components/foo/bar/*.js'
Recompile javascript (rungrunt
console command).
Example: js file,[grung](https://github.com/omalab/oma/blob/03847e519214dafa672954e0c4e1fed4370b8d98/grunt.js#L119)
Basically that's it. We just created a new UI component.